<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><atom:link rel="hub" href="http://tumblr.superfeedr.com/" xmlns:atom="http://www.w3.org/2005/Atom"/><description>Software engineer from Bloomington, Indiana.</description><title>lawrence mcalpin</title><generator>Tumblr (3.0; @lmcalpin)</generator><link>http://www.lmcalpin.com/</link><item><title>bye bye gemcutter</title><description>&lt;p&gt;Starting a few hours ago, I have been getting this error doing almost anything with the gem command:&lt;/p&gt;
&lt;p&gt;ERROR:  While executing gem &amp;#8230; (NoMethodError)&lt;br/&gt;    undefined method `request_uri&amp;#8217; for #&amp;lt;URI::Generic:0x3d49c332&amp;gt;&lt;/p&gt;
&lt;p&gt;When running &amp;#8220;gem update &amp;#8212;system -V&amp;#8221; I noticed that it failed when talking to gemcutter.org.  And then I tried to go there and sure enough some smily blonde with a backpack seems to have taken over the site.  So I guess it&amp;#8217;s gone for good?  At least now I know where to go to get a free credit report or cash advance.&lt;/p&gt;
&lt;p&gt;So while &amp;#8220;undefined method `request_uri&amp;#8217;&amp;#8221; is not exactly my first choice for verbiage to describe this kind of problem, just run this:&lt;/p&gt;
&lt;p&gt;gem sources -r &lt;a href="http://gemcutter.org"&gt;http://gemcutter.org&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;and problem solved&amp;#8230; although I&amp;#8217;ve never had to think about my gem sources before.  Are there any good gem sources I should know about besides the two remaining defaults (rubyforge and github)?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Update&lt;/em&gt;: gemcutter.org is now redirecting to rubygems.org so the steps above should no longer be necessary.&lt;/p&gt;</description><link>http://www.lmcalpin.com/post/22876786730</link><guid>http://www.lmcalpin.com/post/22876786730</guid><pubDate>Fri, 11 May 2012 22:11:00 -0400</pubDate><category>ruby</category></item><item><title>using jruby with aptana</title><description>&lt;p&gt;I enjoy programming in the Ruby language, and I recently started to make the migration to JRuby.  However, I am rather fond of using an IDE for programming.  I know it&amp;#8217;s not trendy; some programmers wear their use of vi as a badge of honor.  I consider it to be archaic.  It&amp;#8217;s like being proud you grunt and swing a bone around.  What separates man from apes is our use of tools, and IDEs are very useful tools.  (Of course, there is a danger with IDEs in that the programmer won&amp;#8217;t learn what is going on behind the scenes: while I agree that every programmer should know HOW to run, maintain, debug, and execute their programs without an IDE, or from within vi and the command line, I strongly disagree that we should always want to.)&lt;/p&gt;
&lt;p&gt;I am also an unabashed fan of Windows.  Yes, it&amp;#8217;s not trendy, but I like the customizability of it.  And, for the record, I haven&amp;#8217;t had any viruses or trojans and I haven&amp;#8217;t seen a blue screen in years.&lt;/p&gt;
&lt;p&gt;On Windows, the best Ruby IDE is Aptana Studio.  I&amp;#8217;ve enjoyed it for quite some time now, but recently I decided to make a more permanent switch to using JRuby.  Unfortunately, Aptana doesn&amp;#8217;t play well with JRuby.  One problem is that it seems to have the Ruby interpreter hardcoded as &amp;#8220;ruby.exe&amp;#8221;.  Not just &amp;#8220;ruby&amp;#8221; (I initially tried making a ruby.bat batch file that would redirect calls to my actual jruby installation), but &amp;#8220;ruby.exe&amp;#8221;. &lt;/p&gt;
&lt;p&gt;So, for a workaround, I created an .exe that spawns jruby.exe (or any other executable) and passes all the same command line arguments on.  So what I do is rename my process launcher as &amp;#8220;ruby.exe&amp;#8221;, stick that in the PATH so Aptana finds the executable it expects to find, configure my launcher .exe to run jruby.exe, and then spawn the child process.  Aptana is none the wiser and everything works beautifully.  Problem solved.&lt;/p&gt;
&lt;p&gt;The code is quite simple.  We simply figure out what directory we are in (so we know where to look for the config file), read it (to figure out what process to launch), fix up the command line arguments (by convention, the first argument should point to the process that is being started, and we don&amp;#8217;t want our child process to get a path to our launcher), and then use _spawnv to launch it.  We do have to take care to quote any arguments with spaces in them as well.&lt;/p&gt;
&lt;pre&gt;int main( int argc, char *argv[] ) {
    // figure out what directory this exe is in
    char path[MAX_PATH];
    string filename(path, GetModuleFileName(NULL, path, MAX_PATH));
    filename = filename.substr(0, filename.find_last_of('\\')+1);
    filename.append("\\predirect.config");
    
    // open the config file
    ifstream configfile(filename.c_str());
    if (configfile.is_open()) {
        // read path to jproc from config file
        string proc;
        getline(configfile, proc);
        configfile.close();

        // call our real proc .exe (or whatever else we 
        const char* new_argv[argc+1];
        for (int i = 0; i &amp;lt; argc; i++) {
            if (i == 0)
                new_argv[0] = quote(proc.c_str());
            else
                new_argv[i] = quote(argv[i]);
        }
        new_argv[argc] = NULL;
        return _spawnv(_P_WAIT, proc.c_str(), new_argv);
    } else {
        cout &amp;lt;&amp;lt; "could not find " &amp;lt;&amp;lt; filename.c_str();
    }
}
&lt;/pre&gt;
&lt;p&gt;&lt;a href="https://github.com/lmcalpin/predirect"&gt;Source code and executable are on Github&lt;/a&gt;.&lt;/p&gt;</description><link>http://www.lmcalpin.com/post/22791135769</link><guid>http://www.lmcalpin.com/post/22791135769</guid><pubDate>Thu, 10 May 2012 15:24:24 -0400</pubDate><category>aptana</category><category>jruby</category><category>c</category></item><item><title>resetting the database in hibernate</title><description>&lt;p&gt;When running unit tests, I find it helpful to reset the database (for unit tests that use the database) before each run to ensure we have a clean slate.  There are a number of ways to do this.  One way would be to the Hibernate property hbm2ddl.auto to &amp;#8220;create-drop&amp;#8221; and force each unit test to use an entirely new SessionFactory.  This isn&amp;#8217;t always a viable option, especially if the SessionFactory is constructed as a subset of other initializations (such as when loading a Spring configuration), as it would be too expensive to reload the entire configuration from scratch for each test.&lt;/p&gt;
&lt;p&gt;Typically, you would want to load those configurations only once for the entire suite.  Because of that, &amp;#8216;create-drop&amp;#8217; would only be run before the first test case executes.  Since I want to reset the database after &lt;em&gt;every single test&lt;/em&gt;, I wrote some code to do so &amp;#8216;by hand.&amp;#8217;&lt;/p&gt;
&lt;p&gt;When using in-memory databases, such as H2 or HSQLDB, this is extremely fast and doesn&amp;#8217;t add any significant delay to your execution time.&lt;/p&gt;
&lt;p&gt;To pull this off, I take advantage of the DatabaseMetadata class Hibernate comes with, which exposes the DROP and CREATE statements that it uses when executing the &amp;#8220;create-drop&amp;#8221; behavior the &amp;#8220;hbm2ddl.auto&amp;#8221; property invokes.&lt;/p&gt;
&lt;pre&gt;@Autowired
LocalContainerEntityManagerFactoryBean lcemfb;

Ejb3Configuration ejb3 = new Ejb3Configuration();
ejb3.configure(lcemfb.getPersistenceUnitInfo(), lcemfb.getJpaPropertyMap());
Configuration config = ejb3.getHibernateConfiguration();
config.buildMappings();
AuditConfiguration.getFor(config); // necessary if you use Envers/Hibernate Audit
Dialect dialect = Dialect.getDialect(config.getProperties());
DatabaseMetadata metadata;
Connection conn = null;
try {
  conn = getConnection();
  metadata = new DatabaseMetadata(conn, dialect);
  DROP_SCRIPTS = config.generateDropSchemaScript(dialect);
  CREATE_SCRIPTS = config.generateSchemaCreationScript(dialect);
} finally {
  close(conn);
}
&lt;/pre&gt;
&lt;p&gt;Then, for each script in DROP_SCRIPTS:&lt;/p&gt;
&lt;pre&gt;Statement stmt = conn.createStatement(); 
for (String sql : DROP_SCRIPTS) { 
  stmt.execute(sql); 
}
&lt;/pre&gt;
&lt;p&gt;and&lt;/p&gt;
&lt;pre&gt;Statement stmt = conn.createStatement(); 
for (String sql : CREATE_SCRIPTS) { 
  stmt.execute(sql); 
} 
&lt;/pre&gt;
&lt;p&gt;Some things to be aware of, however: if you have cacheing enabled, you will encounter errors if Hibernate attempts to load from the cache. Either ensure you don&amp;#8217;t have the second level cache enabled for your unit tests, or explicitly clear the cache by hand:&lt;/p&gt;
&lt;pre&gt;@Autowired
EhCacheManagerFactoryBean cacheManager;

cacheManager.getObject().clearAll();
&lt;/pre&gt;</description><link>http://www.lmcalpin.com/post/19234884155</link><guid>http://www.lmcalpin.com/post/19234884155</guid><pubDate>Tue, 13 Mar 2012 10:00:06 -0400</pubDate></item><item><title>twitter as a global message bus</title><description>&lt;p&gt;&lt;a href="http://www.mediabistro.com/alltwitter/twitter-financials_b19359"&gt;Apparently, Twitter is losing money&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I don&amp;#8217;t understand why.  It is an advanced message bus that allows asynchronous communication between heterogeneous platforms in a dead simple manner.&lt;/p&gt;
&lt;p&gt;One of the systems I work on sits in the middle of a spaghetti nest of queues and topics linking up over a dozen different systems.  We waste so much time doing end to end connectivity tests.  I spent a lot of time writing functionality to archive the messages we receive and send out for debugging purposes, and to allow replay of events in the event that a recoverable or transient error occurs.  Twitter supports archival out of the box.&lt;/p&gt;
&lt;p&gt;Why can&amp;#8217;t Twitter make a private version of their platform that businesses can use internally as a dead simple enterprise service bus?  Their tool already supports many of the features I use every day, and several that I always needed to write by hand.  The Twitter timeline is pub-sub communication.  DMs are a form of point-to-point communication.  Hash tags can be used as message selectors. If I want to replay an event I received yesterday, it&amp;#8217;s archived and I can go back and resend that message.&lt;/p&gt;
&lt;p&gt;The main limitations would be a need for privacy, stability (it would be need to be separated from the global chat room Twitter that we use today), and there would need to be a way to hyperlink to private data streams outside the 140 character limit (that can be securely accessed).  A platform like this would greatly simplify a lot of businesses and let us concentrate on what we really want to be doing: business logic, not plumbing.&lt;/p&gt;
&lt;p&gt;Or, hell, why stop at a private implementation: why can&amp;#8217;t they add a feature to the site we have now that gives you private channels that businesses can use to publish events or information to subscribers (for a fee).  Take a business like &lt;a href="http://www.valuvalu.com/"&gt;ValuValu&lt;/a&gt;, which charges $49 a month for an email that tells you the one mutual fund you need to buy.  Add in a follow-for-a-fee feature and many business like that could dispense with email and just use Twitter&amp;#8217;s platform instead.&lt;/p&gt;
&lt;p&gt;With private channels, you could even use Twitter as a transport for communicating with all kinds of third party APIs.  Let&amp;#8217;s say I want some information from FullContact: just DM them the name, and they reply with a hyperlink to some private endpoint with the results.  It couldn&amp;#8217;t get much simpler.  But the real advantage is that when I talk to Twilio or &lt;strong&gt;any other API&lt;/strong&gt;, I could do it in the exact same manner.&lt;/p&gt;
&lt;p&gt;Twitter should be able to take their technology and turn it into a platform &amp;#8212; a global message bus &amp;#8212; that acts as a transport for the APIs and message publishing needs for businesses all over the world.  And make money doing so - simply building on their already world class infrastructure.&lt;/p&gt;
&lt;p&gt;Instead, they just create things that no one gives a rat&amp;#8217;s ass about like featured tweets&amp;#8230;&lt;/p&gt;</description><link>http://www.lmcalpin.com/post/19191536674</link><guid>http://www.lmcalpin.com/post/19191536674</guid><pubDate>Mon, 12 Mar 2012 15:53:44 -0400</pubDate></item><item><title>brick and mortar retail is obsolete... it's time for them to adapt</title><description>&lt;p&gt;Instead of brick and mortar stores where you buy things, why don&amp;#8217;t we just have places where you go to TRY things (and then order elsewhere). They can charge you an entry fee or make money from additional services (such as unboxing and installation for large items like TVs) or handling returns (drop it off and they box it up and send it wherever.)  I&amp;#8217;m sure someone enterprising enough could even work out a deal with Amazon and/or other online-only retailers to help cover costs in return for driving business to their sites.&lt;/p&gt;
&lt;p&gt;Sucks for you but if people are using your business as a showroom for online purchases, you may as well learn to deal with it, adapt, and figure out how to make money as a showroom.&lt;/p&gt;
&lt;p&gt;Amazon&amp;#8217;s recent Price Check promotion has hit a nerve with retailers and unleashed a massive whinefest &lt;a href="http://www.nytimes.com/2011/12/13/opinion/amazons-jungle-logic.html?_r=1&amp;amp;pagewanted=all"&gt;about how Amazon is destroying brick and mortar businesses&lt;/a&gt;.  Whatever.  You know what?  The world changes.  Deal with it.  If you can&amp;#8217;t figure out how to adapt to a changing world, your business deserves to perish.&lt;/p&gt;</description><link>http://www.lmcalpin.com/post/14172016653</link><guid>http://www.lmcalpin.com/post/14172016653</guid><pubDate>Tue, 13 Dec 2011 12:47:13 -0500</pubDate></item><item><title>java.lang.NoClassDefFoundError: scala/ScalaObject with sbt</title><description>&lt;p&gt;Spent some time trying to figure out why sbt no longer worked for me when I upgraded the sbt-launch jar to the 0.11.0 version.  It would complain about a NoClassDefFoundError on scala/ScalaObject.  0.10.0 and earlier versions of sbt ran perfectly.  The problem wasn&amp;#8217;t related to a project configuration file as this error occurred even if I ran sbt in a completely empty directory.&lt;/p&gt;
&lt;p&gt;Since I&amp;#8217;m knew to scala and sbt, I wasn&amp;#8217;t sure what it was doing behind the scenes, so I didn&amp;#8217;t know where to look.  I&amp;#8217;m sure it&amp;#8217;s documented somewhere but the &lt;a href="http://code.google.com/p/simple-build-tool/wiki/Troubleshooting"&gt;troubleshooting link&lt;/a&gt; I found didn&amp;#8217;t help. &lt;/p&gt;
&lt;p&gt;I knew sbt managed scala versions behind the scenes, so not finding ScalaObject meant that the download was perhaps corrupt.  So the solution was to figure out where sbt puts these things.  I knew it created a local boot folder for new projects I created, but it turns out sbt also keeps a global boot folder under your home folder in ~/.sbt/boot/ (which was C:/Users/&amp;lt;username&amp;gt;/.sbt on my Windows 7 machine). &lt;/p&gt;
&lt;p&gt;Deleting this global boot folder so sbt recreates it was the key.  If you get a similar error message for a specific project, the local boot folder would probably be the culprit in that case.&lt;/p&gt;</description><link>http://www.lmcalpin.com/post/13157731791</link><guid>http://www.lmcalpin.com/post/13157731791</guid><pubDate>Tue, 22 Nov 2011 09:29:16 -0500</pubDate><category>sbt</category><category>scala</category></item><item><title>the mystery of the xcode 4 upgrade, three20, and a blank screen on startup</title><description>&lt;p&gt;Recently, I upgraded to XCode 4, and one of my Objective C programs stopped working properly.  This particular program uses Three20 to manage the application&amp;#8217;s views. &lt;/p&gt;
&lt;p&gt;Upon startup, I would get a blank white screen.  However, if I closed the app by double tapping on the iPhone&amp;#8217;s home button, and then switched back to the already-running instance, I would then see the Three20-managed screens and the app would behave normally.&lt;/p&gt;
&lt;p&gt;Like most puzzlers, the solution turned out to be really simple, though figuring it out was not at all obvious.  It turns out I had left my NIB referencing a window which I never actually used (since Three20 managed loading and switching between my screens), and the app delegate had an outlet connection that pointed to this unused window.  So, apparently, when I converted the app over to use Three20, I hadn&amp;#8217;t cleaned up the NIB to remove the unused outlets and resources. &lt;/p&gt;
&lt;p&gt;This didn&amp;#8217;t cause problems with XCode 3 and earlier, but XCode 4 is pickier, I guess.  No problem: the references didn&amp;#8217;t belong there anyway.  Once I cleaned up the NIB and corresponding @synthesize and IBOutlet references, the programs worked as expected.&lt;/p&gt;</description><link>http://www.lmcalpin.com/post/12609668290</link><guid>http://www.lmcalpin.com/post/12609668290</guid><pubDate>Thu, 10 Nov 2011 15:57:02 -0500</pubDate><category>objective-c</category><category>three20</category></item><item><title>cooler javaFX kreations</title><description>&lt;p&gt;Oracle recently released &lt;a href="http://download.oracle.com/javafx/"&gt;JavaFX&lt;/a&gt; 2, which is a rich client API that ditches the JavaFX language from JavaFX 1.x in favor of a pure Java library.  And man, is it slick.  It makes it very easy to implement rich, graphical applications or applets.&lt;/p&gt;
&lt;p&gt;Inspired by @visualrinse&amp;#8217;s &lt;a href="http://visualrinse.com/coolerkreator/"&gt;Cooler Kreator&lt;/a&gt;, I created my own (greatly simplified)  version of it, which I called &amp;#8220;Cooler Kreations FX&amp;#8221;.  To use it, simply launch it, give it permission to run, type in a tag, and the program will consult Kuler for a random color scheme with the specified tag.  Assuming, of course, that the Kuler API is working at the time (which, lately, hasn&amp;#8217;t been very often&amp;#8230;).&lt;/p&gt;
&lt;p&gt;To create an application is as simple as extending the Application class.&lt;/p&gt;
&lt;pre&gt;public class CoolerKreations extends Application {

    public static void main(String[] args) {
        Application.launch(args);
    }

    @Override
    public void start(Stage stage) {
        stage.setScene(createScene());
    }
 
    private Scene createScene() {
        ....
    }
}
&lt;/pre&gt;
&lt;p&gt;You can use &lt;a href="http://download.oracle.com/javafx/2.0/api/javafx/fxml/doc-files/introduction_to_fxml.html"&gt;FXML&lt;/a&gt; to create your scenes declaratively, or write pure Java code to create your scenes programatically, or mix and match the two.&lt;/p&gt;
&lt;pre&gt;// declaratively, via FXML
Group root = FXMLLoader.load(getClass().getResource("my.fxml"));
Scene scene = new Scene(root, Color.BLACK);

// the FXML:
&amp;lt;VBox fx:controller="com.metatrope.controller.Controller" alignment="center" xmlns:fx="http://javafx.com/fxml" style="-fx-spacing: 5;"&amp;gt;
   &amp;lt;children&amp;gt;
        &amp;lt;HBox alignment="center"&amp;gt;
           &amp;lt;children&amp;gt;
                &amp;lt;Label text="Cooler Kreations" style="-fx-font: 42 Tahoma;" textFill="white" fx:id="title"/&amp;gt;
                &amp;lt;Label text="FX" style="-fx-font-weight: bold; -fx-font-size: 42; -fx-font-style: italic;" textFill="white" fx:id="titlefx"/&amp;gt;
           &amp;lt;/children&amp;gt;
        &amp;lt;/HBox&amp;gt;
   &amp;lt;/children&amp;gt;
&amp;lt;/VBox&amp;gt;

// programatically
Group root = new Group();
Text text = new Text();
text.setText("hi");
root.getChildren().add(text);
Scene scene = new Scene(root, Color.BLACK);
&lt;/pre&gt;
&lt;p&gt;There are a lot of &lt;a href="http://download.oracle.com/javafx/2.0/ui_controls/jfxpub-ui_controls.htm"&gt;controls&lt;/a&gt; available.  Visually, you can style your controls with CSS and there are plenty of effects you can use, such as drop shadows, reflections, blurs, and more.  You can even chain them:&lt;/p&gt;
&lt;pre&gt;Bloom bloom = new Bloom();
bloom.setThreshold(2.0);

BoxBlur blur = new BoxBlur(4 + randomInt(0, 5), 4 + randomInt(0, 5), 4 + randomInt(0, 6));
blur.setInput(bloom);
 // the output of bloom will be the input for this effect

DropShadow ds = new DropShadow();
ds.setOffsetY(4.0f);
ds.setOffsetX(4.0f);
ds.setColor(Color.CORAL);
ds.setInput(blur);
 // the output of blur will be the input for this effect

// apply bloom AND blur AND a drop shadow to this text
text.setEffect(ds);
&lt;/pre&gt;
&lt;p&gt;JavaFX also makes it dead simple to animate controls.  Simply bind a property and identify key points in the timeline, and the system will interpolate all the values in between.  For example, here I tell JavaFX to rotate one of my nodes repeatedly:&lt;/p&gt;
&lt;pre&gt;// loop my node from 0 degrees to 360 degrees, completing one rotation every 15 seconds.
// repeat ad infinitum.
Timeline animation = new Timeline();
animation.getKeyFrames().addAll(
  new KeyFrame(Duration.ZERO, new KeyValue(node.rotateProperty(), 0d)),
  new KeyFrame(Duration.seconds(15.0), new KeyValue(node.rotateProperty(), 360d)));
);
animation.setCycleCount(Animation.INDEFINITE);
animation.play();
&lt;/pre&gt;
&lt;p&gt;This is a huge step forward for rich client development in the Java space and a wonderful replacement for Swing.  On modern JVMs, it even loads quickly in the browser; this wasn&amp;#8217;t historically the case with JavaFX 1.x, or for applets in general, but nowadays Java applets start up almost as fast as Flash (and this will improve even more when Java becomes modularized in future versions.) &lt;/p&gt;
&lt;p&gt;The &lt;a href="https://github.com/lmcalpin/coolerkreationsfx"&gt;source code&lt;/a&gt; can be viewed on my github account.  You can test it out &lt;a href="http://dl.dropbox.com/u/16492687/Demos/CoolerKreationsFX/coolerkreations.html"&gt;online&lt;/a&gt; as well (though only if you use Windows, unfortunately.)  The result could look something like this:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://dl.dropbox.com/u/16492687/Demos/CoolerKreationsFX/scrn1.png"/&gt;&lt;/p&gt;</description><link>http://www.lmcalpin.com/post/12513706561</link><guid>http://www.lmcalpin.com/post/12513706561</guid><pubDate>Tue, 08 Nov 2011 10:27:00 -0500</pubDate><category>java</category><category>javafx</category></item><item><title>force create hibernate envers audit events</title><description>&lt;p&gt;Recently, I had decided to adopt Hibernate Envers to audit changes to several tables on my database.  I decided to attempt to force create the insert events that &lt;em&gt;would&lt;/em&gt; have been generated had I been using Envers from the start.  Unfortunately, there wasn&amp;#8217;t an obvious way to do this, short of writing my own SQL scripts.  That approach is fine, but I had several tables to migrate, and I prefer to avoid bypassing Hibernate when I can.&lt;/p&gt;
&lt;p&gt;This is what I came up with:&lt;/p&gt;
&lt;p&gt;Envers works by using Ejb3 listeners to find out when an entity is inserted, updated, deleted, etc.  So, the obvious solution was to trigger this listener.  The listener is an instance of &lt;a href="http://docs.jboss.org/hibernate/entitymanager/3.4/api/org/hibernate/ejb/event/EJB3PostInsertEventListener.html"&gt;org.hibernate.ejb.event.EJB3PostInsertEventListener&lt;/a&gt; and expects to receive &lt;a href="http://docs.jboss.org/hibernate/core/3.2/api/org/hibernate/event/PostInsertEvent.html"&gt;PostInsertEvents&lt;/a&gt;.&lt;/p&gt;
&lt;pre&gt;PostInsertEvent pie = new PostInsertEvent(entity, entity.getId(), state, persister, source);
eventListener.onPostInsert(pie);
&lt;/pre&gt;
&lt;p&gt;Entity is simply the entity that you saved to the database, so of course we already have that. We just need to figure out what Envers expects for the &lt;em&gt;source&lt;/em&gt;, &lt;em&gt;state&lt;/em&gt;, and the &lt;em&gt;persister&lt;/em&gt;. &lt;/p&gt;
&lt;p&gt;The &lt;em&gt;source&lt;/em&gt; is simple.  This turns out to be the Hibernate session itself, which you can obtain from the JPA EntityManager:&lt;/p&gt;
&lt;pre&gt;EventSource source = (SessionImpl)jpaEntityManager.getDelegate();&lt;/pre&gt;
&lt;p&gt;The &lt;em&gt;persister&lt;/em&gt; is an instance of an &lt;a href="http://docs.jboss.org/hibernate/core/3.3/api/org/hibernate/persister/entity/EntityPersister.html"&gt;EntityPersister&lt;/a&gt;, which just captures the mapping and persistence logic for the given entity.  Every entity has one, and this can be obtained from the EventSource.&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;state&lt;/em&gt; is an object array containing the values of each property that we are persisting.  It can be obtained from the EntityPersister.&lt;/p&gt;
&lt;pre&gt;Object[] state = persister.getPropertyValuesToInsert( entity, null, source ); 
&lt;/pre&gt;
&lt;p&gt;So, basically, all of that information could be obtained with just the entity and the session.  I&amp;#8217;m not sure why they make us pass in all these additional fields when you can get them all from just the EventSource and the entity itself, but whatever.  Once we have all that information, we assemble the PostInsertEvent and pass it to an instance of the AuditEventListener that will do the work.  We don&amp;#8217;t even need to hook into the one that Hibernate creates (from your configuration files), we can just create it &amp;#8220;by hand&amp;#8221;.&lt;/p&gt;
&lt;p&gt;The complete code is this:&lt;/p&gt;
&lt;pre&gt;// instantiate the event listener&lt;br/&gt;AuditEventListener eventListener = new AuditEventListener();&lt;br/&gt;eventListener.initialize(HibConversation.getHibernateConfiguration());&lt;br/&gt;EventSource source = (SessionImpl)jpaEntityManager.getDelegate();
EntityPersister persister = source.getEntityPersister( null, entity ); &lt;br/&gt;&lt;br/&gt;// create an insertion event for each entity you want to audit&lt;br/&gt;Object[] state = persister.getPropertyValuesToInsert( entity, null, source ); 
PostInsertEvent pie = new PostInsertEvent(entity, shippingRate.getId(), state, persister, source); &lt;br/&gt;eventListener.onPostInsert(pie);&lt;/pre&gt;</description><link>http://www.lmcalpin.com/post/9575332365</link><guid>http://www.lmcalpin.com/post/9575332365</guid><pubDate>Tue, 30 Aug 2011 00:05:00 -0400</pubDate><category>java</category><category>hibernate</category><category>envers</category></item><item><title>overriding rails validations metaprogramatically</title><description>&lt;p&gt;I had a need to modify the validations for a model in a Rails 2.3.5 app from a plugin.  I did not want to directly modify the source code; in my case, I was writing my code as a plugin for an existing Rails application so I could upgrade the base code without worrying about losing my changes, or dealing with the hassle of reapplying my patches.  There are several really great Rails frameworks out there that are applications in their own right, such as Redmine and Spree, and writing my customizations as plugins or extensions to them is simply a more flexible solution than modifying the applications directly.&lt;/p&gt;
&lt;p&gt;I was modifying a User class, extending the login length to 255 characters.  We were using emails as the login, and where I work they can get pretty long because they are usually a concatenation of one&amp;#8217;s first and last names.  And some of my co-workers have obscenely long names.  Directly modifying User would be trivial &amp;#8212; you would just increase the value associated with the maximum attribute for the validates_length_of validation we are changing:&lt;/p&gt;
&lt;pre&gt;validates_length_of :login, :maximum =&amp;gt; 255
&lt;/pre&gt;
&lt;p&gt;But, as I mentioned, I did not want to change the original code.  So, we need to get at the list of validation callbacks.  Luckily, that&amp;#8217;s easy: there&amp;#8217;s a &lt;strong&gt;@validate_callbacks&lt;/strong&gt; instance method available to us.  So, we just need to iterate over it and find the callback that we don&amp;#8217;t want.&lt;/p&gt;
&lt;p&gt;Each entry in &lt;strong&gt;@validate_callbacks&lt;/strong&gt; is an instance of ActiveSupport::Callbacks::Callback.  This class contains an accessor called &lt;em&gt;method&lt;/em&gt; which returns the Proc that is executed to run the validation.  Unfortunately, we want to get at the values being sent to that proc.  We know that the &lt;em&gt;&lt;a href="http://apidock.com/rails/ActiveModel/Validations/ClassMethods/validates_length_of"&gt;validates_length_of&lt;/a&gt;&lt;/em&gt; method takes in an attrs parameter, so we just &lt;em&gt;&lt;a href="http://corelib.rubyonrails.org/classes/Kernel.html#M002041"&gt;eval&lt;/a&gt;&lt;/em&gt; that against the callback method&amp;#8217;s &lt;em&gt;&lt;a href="http://www.ruby-doc.org/core/classes/Proc.html#M000559"&gt;binding&lt;/a&gt;&lt;/em&gt; to find the list of attributes that this proc will validate.&lt;/p&gt;
&lt;p&gt;Because we know we only passed one attribute in (instead of a chain of them), we just check the first value, and double check that the &lt;em&gt;maximum&lt;/em&gt; option was set to 30 (which is the original value).  This also allows us to easily filter out the other validations on the login field that we aren&amp;#8217;t interested in, such as &lt;em&gt;validates_format_of&lt;/em&gt;.  The finished product looks something like this:&lt;/p&gt;
&lt;pre&gt;require_dependency 'user'
require 'dispatcher'
module UserPatch
def self.included(base)
  base.class_eval do
    @validate_callbacks.reject! { |c| true if Proc === c.method &amp;amp;&amp;amp;
      eval("attrs", c.method.binding).first == :login &amp;amp;&amp;amp; c.options[:maximum] == 30 rescue false }
    validates_length_of :login, :maximum =&amp;gt; 255 # new value&lt;br/&gt;  end
end
Dispatcher.to_prepare do
 unless User.included_modules.include?(UserPatch)
   User.send(:include, UserPatch)
 end
end
&lt;/pre&gt;</description><link>http://www.lmcalpin.com/post/5219540409</link><guid>http://www.lmcalpin.com/post/5219540409</guid><pubDate>Thu, 05 May 2011 11:38:24 -0400</pubDate><category>ruby</category><category>rails</category></item><item><title>building a redmine plugin</title><description>&lt;p&gt;I was experimenting with the &lt;a href="http://www.redmine.org/"&gt;Redmine&lt;/a&gt;, a popular Ruby on Rails open source project management web application.  It&amp;#8217;s pretty full featured: you can set up multiple projects, each with its own issue tracking, wikis, document stores, and calendars, all within the same instance of Redmine.  But it didn&amp;#8217;t have everything I wanted.&lt;/p&gt;
&lt;p&gt;One problem that I quickly realized I wouldn&amp;#8217;t be able to live with is that emails sent from a Redmine instance all use the same emission address.  For me, this was a showstopper, since I had a requirement that each project would be tied to its own email address, which our users email for tech support.  So I set out to figure out how to customize Redmine.  While it would be trivial to simply modify Redmine&amp;#8217;s source code directly, I wanted to be able to upgrade the original system, while preserving my customizations.  The ideal way to do that is to create a plugin.&lt;/p&gt;
&lt;p&gt;To start a Redmine plugin project is simple - there is a Rails generator for that:&lt;/p&gt;
&lt;pre&gt;ruby script/generate redmine_plugin &amp;lt;plugin_name&amp;gt;&lt;/pre&gt;
&lt;p&gt;In my case, I called it &amp;#8220;project_email&amp;#8221;.  This creates your standard folder hierarchy for a Rails app: controllers, helpers, models, views, db, as well as a lib folder.  The most important file is init.rb, which is invoked when the plugin is loaded.  This contains some information that Redmine needs.&lt;/p&gt;
&lt;pre&gt;require 'redmine'&lt;br/&gt;require 'mailer_patch'&lt;br/&gt;require 'project_patch'&lt;br/&gt;&lt;br/&gt;Redmine::Plugin.register :redmine_redmine_project_email do&lt;br/&gt;  name 'Redmine Project Email plugin'&lt;br/&gt;  author 'Lawrence McAlpin'&lt;br/&gt;  description 'Adds a per-project email emission address'&lt;br/&gt;  version '0.0.1'&lt;br/&gt;  url 'http://github.com/lmcalpin/redmine_project_email'&lt;br/&gt;  author_url 'http://www.lmcalpin.com/'&lt;br/&gt;end&lt;br/&gt;&lt;/pre&gt;
&lt;p&gt;Like any Rails plugin, we can add our own tables and fields.  We simply create a new migration that looks like this:&lt;/p&gt;
&lt;pre&gt;class AddMailFromToProject &amp;lt; ActiveRecord::Migration&lt;br/&gt;  def self.up&lt;br/&gt;      add_column :projects, :mail_from, :string&lt;br/&gt;  end&lt;br/&gt;&lt;br/&gt;  def self.down&lt;br/&gt;    remove_column :projects, :mail_from&lt;br/&gt;  end&lt;br/&gt;end&lt;br/&gt;&lt;/pre&gt;
&lt;p&gt;&amp;#8230; and run &lt;em&gt;rake db:migrate:plugins&lt;/em&gt; to load it up!  Now, the &amp;#8220;project&amp;#8221; model will automagically have a new property called &amp;#8220;&lt;em&gt;mail_from&lt;/em&gt;.&amp;#8221;&lt;/p&gt;
&lt;p&gt;At this point, I need to override some of Redmine&amp;#8217;s controllers and models.  The problem is: anything loaded by the plugin will be overwritten by the base application.  That is not quite what we want.  Luckily, Ruby makes it incredibly easy to tame those classes: through &lt;a href="http://www.amazon.com/gp/product/1934356476/ref=as_li_ss_tl?ie=UTF8&amp;amp;tag=lawmcasblo-20&amp;amp;linkCode=as2&amp;amp;camp=217145&amp;amp;creative=399349&amp;amp;creativeASIN=1934356476"&gt;metaprogramming&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We set up a few modules with our patches and force the class to include it. &lt;/p&gt;
&lt;pre&gt;require_dependency 'mail_handler'&lt;br/&gt;&lt;br/&gt;module MailerPatch&lt;br/&gt;    def self.included(base) # :nodoc:&lt;br/&gt;        base.send(:include, InstanceMethods)&lt;br/&gt;        base.class_eval do&lt;br/&gt;            alias_method_chain :issue_add, :project_emission_email&lt;br/&gt;            # ... override the rest of the methods as well&lt;br/&gt;        end&lt;br/&gt;    end&lt;br/&gt;    module InstanceMethods&lt;br/&gt;      def issue_add_with_project_emission_email(issue)&lt;br/&gt;        from_project issue&lt;br/&gt;        issue_add_without_project_emission_email issue&lt;br/&gt;      end&lt;br/&gt;      def from_project(container)&lt;br/&gt;        unless container.nil? || container.project.nil? || container.project.mail_from.nil? || container.project.mail_from.empty?&lt;br/&gt;          from container.project.mail_from&lt;br/&gt;        end&lt;br/&gt;      end&lt;br/&gt;    end&lt;br/&gt;end&lt;br/&gt;&lt;/pre&gt;
&lt;p&gt;This code is straightforward: we override the issue_add method.   alias_method_chain takes in two parameters, the first being a symbol representing the method we are overriding, as well as a suffix.  In our case, we use &amp;#8220;project_emission_email&amp;#8221; as the suffix, so the alias_method_chain call will rename the original issue_add method to &amp;#8220;issue_add_without_project_emission_email&amp;#8221; and rename the &amp;#8220;issue_add_&lt;strong&gt;with&lt;/strong&gt;_project_emission_email&amp;#8221; method that &lt;strong&gt;we&lt;/strong&gt; define to &amp;#8220;issue_add&amp;#8221;.  Any existing code that calls issue_add will end up calling our &amp;#8220;issue_add_with_project_emission_email&amp;#8221; method.&lt;/p&gt;
&lt;p&gt;We simply override the original mailer to set the from address to the value set in the new &amp;#8220;&lt;em&gt;mail_from&lt;/em&gt;&amp;#8221; field we added to our project.  If no customized &amp;#8220;mail_from&amp;#8221; is set for a project, the default emission email will be used.&lt;/p&gt;
&lt;p&gt;But now we have a problem: Redmine ignores any attributes not specifically marked as &amp;#8220;safe.&amp;#8221;  So we need to modify the project model to add a call to&lt;/p&gt;
&lt;pre&gt;safe_attributes 'mail_from'&lt;/pre&gt;
&lt;p&gt;No problem!  Monkey patching to the rescue!&lt;/p&gt;
&lt;pre&gt;module ProjectPatch&lt;br/&gt;    def self.included(base) # :nodoc:&lt;br/&gt;        base.class_eval do&lt;br/&gt;          unloadable&lt;br/&gt;          safe_attributes 'mail_from'&lt;br/&gt;        end&lt;br/&gt;    end&lt;br/&gt;end&lt;br/&gt;&lt;/pre&gt;
&lt;p&gt;Unfortunately, in development mode, our model appears to be reloaded upon every request!  And, you know what?  The same thing happens to our mailer!  Oh nos.  But hey, no problem, we&amp;#8217;ll just patch the Rails dispatcher to reapply the patch every time:&lt;/p&gt;
&lt;pre&gt;Dispatcher.to_prepare do&lt;br/&gt;  unless Project.included_modules.include?(ProjectPatch)&lt;br/&gt;    Project.send(:include, ProjectPatch)&lt;br/&gt;  end&lt;br/&gt;  unless Mailer.included_modules.include?(MailerPatch)&lt;br/&gt;    Mailer.send(:include, MailerPatch)&lt;br/&gt;  end&lt;br/&gt;end&lt;br/&gt;&lt;/pre&gt;
&lt;p&gt;Now we&amp;#8217;re almost done!  We just need to modify the view.  The easiest way would be to simply add our own customized _form.rhtml in the app/views/projects folder.  Unlike controllers and models, the views in our plugin take precedence, so our _form.rhtml will be loaded instead of the one included in Redmine.&lt;/p&gt;
&lt;p&gt;Redmine provides a hook that lets you add new fields, without overriding the entire view file.  This would be the better approach (since a future version of Redmine may have other UI changes that we want) but it&amp;#8217;s late, and this beer isn&amp;#8217;t going to drink itself, so we&amp;#8217;ll just stop here.  We&amp;#8217;ll learn about &lt;a href="http://www.redmine.org/projects/redmine/wiki/Hooks"&gt;plugin hooks&lt;/a&gt; another time.&lt;/p&gt;</description><link>http://www.lmcalpin.com/post/5057982222</link><guid>http://www.lmcalpin.com/post/5057982222</guid><pubDate>Fri, 29 Apr 2011 22:10:00 -0400</pubDate><category>ruby</category><category>rails</category><category>redmine</category></item><item><title>something to offer besides waiting to die</title><description>&lt;a href="http://wordsofadvice4young.blogspot.com/2010/11/something-to-offer-besides-waiting-to.html"&gt;something to offer besides waiting to die&lt;/a&gt;: &lt;p&gt;Recently I had a discussion with @SoundSystemSDC about small companies in small towns competing to attract and retain professional tech talent and stem the brain drain.  This topic had come up in the recent The Combine conference here in Bloomington, Indiana.  A group of Midwestern executives discussed the challenges of tech companies in the Midwest.  During the Q&amp;A session, I asked how an Indiana business can compete given the gross disparity in compensation that you have compared to larger cities like New York City and San Francisco.  I even pointed out a job description for a Wall Street job that paid in the six digits and pointed out how much more it was than a similar job for something in Indianapolis.  The response was simply “well it’s better to raise a family here and you can’t buy a home in San Francisco.”  Which no one really cares about when they first go on the job market.  And once you’re launched on your career path, moving to the middle of nowhere isn’t generally considered a step up.&lt;/p&gt;
&lt;p&gt;Sorry.  If you’re in a small town and you want to attract and retain top tech professionals you’re going to have to try harder than that.&lt;/p&gt;
&lt;p&gt;What can a small town with small companies do to attract and retain the top tech talent?  Well, how about:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Alternate Compensation&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Offer equity compensation to make up for the smaller salary compensation.  Let them use some company resources for personal projects.  Or something else.  I don’t know.  Be creative.  But compensation doesn’t always have to be pecuniary.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Quality of Life&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you can’t pay Wall Street wages, don’t demand Wall Street hours.  In New York City, day cares close at 7:30pm.  The day care my daughter goes to here in Bloomington closes at 5:30pm.  The day cares close at 7:30 in NYC because people are still working then.  You want that top talent to move over to you, but you can’t pay the same?  Point out that a move from a 60 hour week to a 40 hour week takes into account 33% of that wage difference already.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Embrace Attrition&lt;br/&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Developers crave new experiences.  Accept it and embrace it.  Get smaller companies within the same community to work together to find ways that can allow for employees who want new experiences to move ‘laterally’ to other companies in the area.  That is: help your employees get a job with other companies in your area. &lt;/p&gt;
&lt;p&gt;If you work for a larger company, chances are they  make it easy to apply for dozens of other opportunities as they arise within the same company.  Even outside of the larger companies, in NYC, Chicago, or SF, you can find hundreds of job opportunities with the drop of a hat.  I got cold calls from recruiters daily.  Here in Indiana, not so much.  Realize that people want the opportunity to move on to other opportunities and develop new skills or work on something new.  Make it easy for them to do so.  Brain drain is bad for everyone; but it’s better to lose your best guy to someone up the street than to see them leave the local community (or the state) entirely.  And if you help them go on good terms, they’re more likely to come back.&lt;/p&gt;
&lt;p&gt;Also, the cross pollination within the community creates additional bonds that help retain that talent.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Promote the Community&lt;br/&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Use the power of local government or band together with fellow local businesses to promote each other and local leaders in the tech community.  People want to be recognized for their accomplishments.  Big companies and big cities tend to anonymize people: even the cream of the crop can easily end up being no more than a small fish in a BIG pond.  Maybe they’d rather come here where they can be a big fish in a small pond.  But give them the satisfaction of having people around who will notice that.  Otherwise, they’re no better off.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pay Them What They’re Worth, But Be Selective&lt;br/&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you can afford it, suck it up and pay them what they can earn.  People like money, and the better cost of living &lt;em&gt;is&lt;/em&gt; attractive &lt;em&gt;when your salary is the same&lt;/em&gt;.  Obviously this is a risky approach.  No one wants to get stuck with a total dud who soaks up twice the salary.  But if you’re smart and you’re careful, the experiences these developers have honed in the bigger and much more highly competitive markets can be very beneficial to you - and that one developer &lt;em&gt;can &lt;/em&gt;very likely be worth a small team. &lt;/p&gt;
&lt;p&gt;I noticed a huge increase in the caliber of the developers I worked with when I first moved to Chicago (and, later, New York City) from the smaller Midwestern town I first worked in (even though I worked at a Fortune 50 company that could afford to pay a pretty competitive rate.)  Where I worked initially, people usually came in straight out of college and stayed there their entire lives.  Developers I worked with in Chicago and New York City, on the other hand, were constantly exposed to new ideas and new concepts and tended to learn a lot more.  Sure, the internet helps spread those ideas to even the remote places on Earth, but the fact is the big cities attract the better developers since there are more challenges there and more people to learn from.  You can get more developers for the same amount of money here in the Midwest, but you often get what you pay for.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Telework&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;OK, maybe you can’t match that six digit coastal salary after all.  Sadness.  But I bet that just as that New York City salary dwarfs our Midwestern Indiana tech salaries, there are places where our measly offering would be pretty attractive.  Where people might want to live despite the fact that it’s not here in Bloomington, for whatever inexplicable reason they might have.&lt;/p&gt;
&lt;p&gt;Once upon a time, that might have been a deal breaker.  Businesses tended to form near related businesses in the past for a reason.  Distance made it harder to trade, communicate, and meet one another.  Nowadays, a little invention called the Internet makes it easy to do all three of those things in our underwear.  With miles and miles between each of us.  So why are we still expecting everyone to sit down next to each other?  In my experience telecommuting, I can assure you, I am far more productive now that I have fewer officeplace distractions.&lt;/p&gt;
&lt;p&gt;So while your Big City competitors are busy paying half of their budget on overpriced real estate and have half of their workforce tied up suiting up and battling a century old subway system, you can focus on more important things like real work with real people wherever they happen to want to live.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Anything Else?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;There are probably plenty of ideas out there that a smaller town with small companies can do to make itself more attractive besides compensation.  But seriously guys, give up on the cost of living calculator argument.  It’s not compelling.  If cost of living is your argument, we may as well move to McAllen, Texas.  &lt;a href="http://www.forbes.com/2009/10/12/most-impoverished-cities-business-beltway-poverty-cities_slide_2.html"&gt;I hear it’s pretty cheap to live there&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You want to stop brain drain?  Either match the coastal salaries, drain brains from some other community (via teleworking), and/or find a way to nurture a stronger sense of community that instills a sense of belonging, where ones’ successes are noticed and celebrated, and ones’ skills are actively developed - even if it means working within the local community to make it easier - or encourages - people - and their ideas - to move from company to company.&lt;/p&gt;</description><link>http://www.lmcalpin.com/post/1727233117</link><guid>http://www.lmcalpin.com/post/1727233117</guid><pubDate>Mon, 29 Nov 2010 09:30:00 -0500</pubDate></item><item><title>i stuck my cucumber in it</title><description>&lt;p&gt;We&amp;#8217;re building out an application to support this high profile effort that involves something like 10 different teams.  My team&amp;#8217;s application has over a million lines of code, 8000 classes, and Needs To Work(tm).  Or heads will roll.  And mine doesn&amp;#8217;t like to do that, because it might get all scruffed up.  So naturally we decided to get down with the BDD and use the &lt;a href="http://cukes.info/"&gt;Cucumber&lt;/a&gt;.  But since we&amp;#8217;re enterprise Java developers, things get a little more complicated.  Because that&amp;#8217;s how we roll.&lt;/p&gt;
&lt;p&gt;We use &lt;a href="http://jruby.org/"&gt;JRuby&lt;/a&gt; so our Ruby code can talk to our Java code and it&amp;#8217;s totally awesome and all that.  But when it comes to deploying, right now we have a simple process that involves a script (using a proprietary internal tool that is kind of like SCP except it leaves me wishing it actually was) that bundles up all my deliverables and sticks it on the target server.  The application servers and Java platforms and so on are already there, usually maintained by other teams.&lt;/p&gt;
&lt;p&gt;I wanted to build the application on a build server where the features will be run whenever code changes (using hudson to trigger the scripts).  I know what versions of Java will be available on the target servers, since there are architectural standards within the enterprise that I can count on.  And, among those standards, I can count on not having any variety of Ruby anywhere unless I put it there myself.  But that complicates our process, because I really shouldn&amp;#8217;t be adding things to the server (which my team doesn&amp;#8217;t own or control).  And even if I did, then the server would have an additional component that existed nowhere else which would need to be maintained and loved and cared for, and I&amp;#8217;m not at all into that sort of thing.&lt;/p&gt;
&lt;p&gt;So I says to myself: how do I simplify this process?  And myself says back: stick your cucumber in it.&lt;/p&gt;
&lt;p&gt;So I did.  But what does that mean, you say?  Well, besides being what the cool Java kids are calling it these days, what I mean is that I stuck &lt;a href="http://cukes.info/"&gt;Cucumber&lt;/a&gt; and its dependent gems inside the JRuby jar which meant that all I needed to do was bundle a single extra jar in with the application that we build.  This makes deploying the exact same version of Ruby with the exact same gems to any machine or environment really easy: you just copy one file around the network.  Even a caveman could do it.  But TCP/Smoke Signal was notoriously slow and error prone so they usually didn&amp;#8217;t.&lt;/p&gt;
&lt;p&gt;The process is super easy to do.  First of all, you need to download the source code.  You can get it from github (&lt;a href="http://github.com/jruby/jruby"&gt;&lt;a href="http://github.com/jruby/jruby"&gt;http://github.com/jruby/jruby&lt;/a&gt;&lt;/a&gt;) or just download the source jar: &lt;a href="http://jruby.org/download"&gt;&lt;a href="http://jruby.org/download"&gt;http://jruby.org/download&lt;/a&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;What we want to do is build the jar-complete version of the distributable, which is a completely standalone JRuby environment encapsulated as a single jar.  If you inspect the ant build script (which is like a make file in the Java world), you&amp;#8217;ll see the target &amp;#8220;jar-complete&amp;#8221; invokes a command to install additional gems defined in the &amp;#8220;complete.jar.gems&amp;#8221; property.  This will by default be found in the &amp;#8220;default.build.properties&amp;#8221; file.  I just edited it directly, and added a reference to a new property &amp;#8220;cucumber.gems&amp;#8221; to the end:&lt;/p&gt;
&lt;p&gt;complete.jar.gems=${rspec.gem} ${rake.gem} {$ruby.debug.gem} ${ruby.debug.base.gem} ${columnize.gem} ${cucumber.gems}&lt;/p&gt;
&lt;p&gt;Then we need to define the cucumber gems we want.  To ensure the build is predictable, I specify each gem and dependency along with its version:&lt;/p&gt;
&lt;p&gt;cucumber.gems=${build.lib.dir}/cucumber-0.9.2.gem ${build.lib.dir}/builder-2.1.2.gem ${build.lib.dir}/diff-lcs-1.1.2.gem ${build.lib.dir}/gherkin-2.2.9-java.gem ${build.lib.dir}/json-1.4.6-java.gem ${build.lib.dir}/term-ansicolor-1.0.5.gem&lt;/p&gt;
&lt;p&gt;Now you need to get the gem files and put them in the jruby_src/build_lib folder.  When you run the build, it will download the actual gem sources.  I just copied the gem files from an existing JRuby installation&amp;#8217;s gem cache (jruby/lib/ruby/gems/1.8/cache), but you can do it any way you want.&lt;/p&gt;
&lt;p&gt;Now run &amp;#8220;ant dist-jar-complete&amp;#8221; and you&amp;#8217;ll be presented with a lovely, customized version of jruby-complete-1.x.y.jar in your jruby_src/dist folder ready for the cukes or whatever else you want.&lt;/p&gt;
&lt;p&gt;You could then invoke it by calling:&lt;/p&gt;
&lt;pre&gt;java -jar jruby-complete-1.5.3.jar -S cucumber features
&lt;/pre&gt;</description><link>http://www.lmcalpin.com/post/1373642187</link><guid>http://www.lmcalpin.com/post/1373642187</guid><pubDate>Fri, 22 Oct 2010 10:43:00 -0400</pubDate><category>cucumber</category><category>java</category><category>bdd</category><category>jruby</category><category>ruby</category></item><item><title>hello world from scalatra</title><description>&lt;p&gt;There&amp;#8217;s been some buzz lately about Scalatra, which is a Sinatra like framework for Scala.  Sinatra is a very scaled down platform for web programming in Ruby.  Unlike many web frameworks (such as Lift, JSF, etc.) which tend to be very stateful and try to abstract away from the HTML and web technologies, Sinatra does no such thing.  It&amp;#8217;s very low level, which can make it very fast to get up and going for smaller, stateless web applications, especially REST based services.  Scalatra is an attempt to bring that to the Scala world.&lt;/p&gt;
&lt;p&gt;To create our Hello World webapp in Scalatra, we&amp;#8217;ll first create a dummy project.  Create a new folder to hold our project and use the &lt;a href="http://code.google.com/p/simple-build-tool/"&gt;simple build tool&lt;/a&gt; (sbt) to create your project.&lt;/p&gt;
&lt;pre&gt;md HelloScalatra
cd HelloScalatra
sbt
&lt;/pre&gt;
&lt;p&gt;You&amp;#8217;ll get output like this:&lt;/p&gt;
&lt;pre&gt;Project does not exist, create new project? (y/N/s) y
Name: HelloScalatra
Organization: test
Version [1.0]:
Scala version [2.7.7]: 2.8.0
sbt version [0.7.4]:
&lt;/pre&gt;
&lt;p&gt;Now you need to tell the simple build tool what additional libraries you need for your project. We&amp;#8217;ll create a project build file to do that. This works kind of like a Gemfile in the sense that it lets the build tool know what dependencies we have. The build file is written in Scala itself.&lt;/p&gt;
&lt;p&gt;Create the file ScalatraBuild.scala in the HelloScalatra/project/build folder.&lt;/p&gt;
&lt;pre&gt;// save as project/build/HelloScalatraBuild.scala
import sbt._

class ScalatraBuild(info: ProjectInfo) extends DefaultWebProject(info) 
{
  // scalatra
  val sonatypeNexusSnapshots = "Sonatype Nexus Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots"
  val sonatypeNexusReleases = "Sonatype Nexus Releases" at "https://oss.sonatype.org/content/repositories/releases"
  val scalatra = "org.scalatra" %% "scalatra" % "2.0.0-SNAPSHOT"
 
  // jetty
  val jetty6 = "org.mortbay.jetty" % "jetty" % "6.1.22" % "test"
  val servletApi = "org.mortbay.jetty" % "servlet-api" % "2.5-20081211" % "provided"
}
&lt;/pre&gt;
&lt;p&gt;Now download the dependencies. This is similar to running bundle install in a Rails app.&lt;/p&gt;
&lt;pre&gt;sbt update
&lt;/pre&gt;
&lt;p&gt;One drawback of Scalatra is that it is a Servlet-based framework. That means we aren&amp;#8217;t getting away without creating a web.xml file. So let&amp;#8217;s set that up. Since simple build tool uses maven conventions, we need to do that in the HelloWorld/src/main/webapp/WEB-INF folder.&lt;/p&gt;
&lt;pre&gt;HelloWorld/src/main/webapp/WEB-INF/web.xml:

&amp;lt;web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee &lt;a href="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"&gt;http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd&lt;/a&gt;"
         version="2.5"&amp;gt;
    &amp;lt;servlet&amp;gt;
        &amp;lt;servlet-name&amp;gt;HelloWorld
        &amp;lt;servlet-class&amp;gt;com.test.HelloWorld
    &amp;lt;/servlet&amp;gt;

    &amp;lt;servlet-mapping&amp;gt;
        &amp;lt;servlet-name&amp;gt;HelloWorld
        &amp;lt;url-pattern&amp;gt;/*
    &amp;lt;/servlet-mapping&amp;gt;
&amp;lt;/web-app&amp;gt;
&lt;/pre&gt;
&lt;p&gt;This says that we will have a Servlet handled by the com.test.HelloWorld.scala file (which we haven&amp;#8217;t written yet) and it will respond on all URL patterns.&lt;/p&gt;
&lt;p&gt;Now we can actually write our app. Simply create the HelloWorld/src/main/scala/com/test/HelloWorld.scala file:&lt;/p&gt;
&lt;pre&gt;HelloWorld/src/main/scala/com/test/HelloWorld.scala:

package com.test

import org.scalatra._

class HelloWorld extends ScalatraServlet {
    get("/") {
        "Hello World"
    }
}
&lt;/pre&gt;
&lt;p&gt;Now we can start the web server:&lt;/p&gt;
&lt;pre&gt;sbt jetty
&lt;/pre&gt;
&lt;p&gt;And we can browse to http://localhost:8080/ and we&amp;#8217;ll see:&lt;/p&gt;
&lt;pre&gt;Hello World
&lt;/pre&gt;</description><link>http://www.lmcalpin.com/post/1302820836</link><guid>http://www.lmcalpin.com/post/1302820836</guid><pubDate>Tue, 12 Oct 2010 21:49:14 -0400</pubDate><category>scala</category><category>scalatra</category></item><item><title>jstl tags not working in jsf 2</title><description>&lt;p&gt;I was migrating a JSF application to JSF 2 and noticed that none of the JSTL tags worked anymore.  And Googling for a reason for that hasn&amp;#8217;t been very helpful as 99% of the posts regarding &amp;#8220;JSTL and JSF&amp;#8221; just say &amp;#8220;don&amp;#8217;t&amp;#8221;. &lt;/p&gt;
&lt;p&gt;The prevailing wisdom used to be that you shouldn&amp;#8217;t mix JSTL and JSF, and once upon a time that was very true.  But JSF and JSTL has worked pretty well together since at least 1.2, and while in general you should avoid JSTL when there&amp;#8217;s an equivalent purely JSF-based solution, there &lt;em&gt;are&lt;/em&gt; times when it just makes more sense to use JSTL.  So I was disappointed at first to see that this didn&amp;#8217;t appear to be working anymore.&lt;/p&gt;
&lt;p&gt;Well, it turns out, JSF 2&amp;#8217;s Facelets specification requires support for JSTL and both major implementations includes the taglib.xml so we&amp;#8217;re good.  There&amp;#8217;s no reason to rewrite all those .xhtml files just yet.&lt;/p&gt;
&lt;p&gt;It turns out the problem was simply that the taglib namespace had changed from&lt;/p&gt;
&lt;p&gt;      xmlns:c=&amp;#8221;http://java.sun.com/jstl/core&amp;#8221;&lt;/p&gt;
&lt;p&gt;to&lt;/p&gt;
&lt;p&gt;      xmlns:c=&amp;#8221;http://java.sun.com/jsp/jstl/core&amp;#8221;&lt;/p&gt;
&lt;p&gt;I couldn&amp;#8217;t find documentation anywhere about that, so here you go, Googlers.  Hopefully I saved a few of you a couple of headscratching minutes.&lt;/p&gt;</description><link>http://www.lmcalpin.com/post/1262495557</link><guid>http://www.lmcalpin.com/post/1262495557</guid><pubDate>Wed, 06 Oct 2010 23:53:42 -0400</pubDate><category>jsf</category><category>java</category><category>jstl</category></item><item><title>getting a generic List from a JAXB-RS Web service</title><description>&lt;p&gt;If you consume a JAXB-RS web service using Jersey, you might encounter an issue when attempting to construct a generic List returned by the service.  To get a simple object, you would simply call this code:&lt;/p&gt;
&lt;pre&gt;Client client = Client.create();
Foo foo = client.resource(url).type(mimeType).get(Foo.class);
&lt;/pre&gt;
&lt;p&gt;But because of &lt;a href="http://download.oracle.com/javase/tutorial/java/generics/erasure.html"&gt;type erasure&lt;/a&gt;, this isn&amp;#8217;t as straightforward for returning a generic collection.  As with most APIs that require type-information at runtime for generics, you have to pass in a type token.  With Jersey, you can do that by passing in a concrete  instance of com.sun.jersey.api.client.GenericType.&lt;/p&gt;
&lt;pre&gt;Client client = Client.create();
List listOfFoos = client.resource(url).type(mimeType).get(new GenericType&amp;lt;List&amp;lt;Foo&amp;gt;&amp;gt;() {});
&lt;/pre&gt;
&lt;p&gt;This works because when you create a construct a subclass for a generic type, the  class can, via reflection, obtain its own parameterized type.&lt;/p&gt;
&lt;pre&gt;Type superclass = getClass().getGenericSuperclass();
Type myTypeArguments = ((ParameterizedType)superclass).getActualTypeArguments()[0];
&lt;/pre&gt;
&lt;p&gt;This is why GenericType is abstract and you are forced to instantiate a subclass with the type information you want Jersey to know about.&lt;/p&gt;
&lt;p&gt;Not exactly an ideal solution (reified generics would be better), but it gets the job done.&lt;/p&gt;</description><link>http://www.lmcalpin.com/post/1257451410</link><guid>http://www.lmcalpin.com/post/1257451410</guid><pubDate>Wed, 06 Oct 2010 16:33:00 -0400</pubDate><category>type tokens</category><category>generics</category><category>java</category><category>jersey</category><category>jaxb-rs</category></item><item><title>hello web from ada</title><description>&lt;p&gt;I decided to mess around with some Ada.  This is an old school compiled language, that is popular with the Department of Defense and almost nobody else.  Except me.  Mainly because I like the name.  It&amp;#8217;s pretty.&lt;/p&gt;
&lt;p&gt;So here&amp;#8217;s what you do:&lt;/p&gt;
&lt;p&gt;1) Download the GPL version of GNAT from &lt;a href="http://libre.adacore.com/libre/download2"&gt;AdaCore&lt;/a&gt;.  Make sure you grab AWS also.&lt;/p&gt;
&lt;p&gt;2) If you are using Windows, you will need to have a Unix shell prompt available to you.  You can get this using Cygwin or &lt;a href="http://www.mingw.org/"&gt;MINGW&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;3) Install GNAT.&lt;/p&gt;
&lt;p&gt;4) Unzip the AWS source code.  In a moment, we will build this library.  For some reason, on my machine, it didn&amp;#8217;t auto-detect the install directory of GNAT properly, so first edit makefile.conf and update the prefix line to point to that directory you installed GNAT into.&lt;/p&gt;
&lt;p&gt;5) Run &amp;#8220;make setup build install&amp;#8221; to install AWS libraries so your projects can find them. &lt;/p&gt;
&lt;p&gt;6) Go into the templates_parser subdirectory and edit makefile.setup to change your installation directory and run &amp;#8220;make install&amp;#8221;. &lt;/p&gt;
&lt;p&gt;There is no standard way to install libraries so you have to actually read the README and INSTALL files.&lt;/p&gt;
&lt;p&gt;7) Use GPS (which comes with GNAT) or install GNATBench (Eclipse plugin) to set up a new Ada project.  Declare the main source file to be &amp;#8220;Server.adb&amp;#8221;.&lt;/p&gt;
&lt;p&gt;8) Create &amp;#8220;Server.adb&amp;#8221;:&lt;/p&gt;
&lt;pre&gt;Server.adb:&lt;br/&gt;&lt;br/&gt;with GNAT.IO;  use GNAT.IO;&lt;br/&gt;with AWS.Default;&lt;br/&gt;with AWS.Server;&lt;br/&gt;with ServerCallback;&lt;br/&gt;&lt;br/&gt;procedure Server is&lt;br/&gt;   WS : AWS.Server.HTTP;&lt;br/&gt;begin&lt;br/&gt;   AWS.Server.Start (WS, "Hello World",&lt;br/&gt;                     Max_Connection =&amp;gt; 1,&lt;br/&gt;                     Callback =&amp;gt; ServerCallback.Echo'Access);&lt;br/&gt;   AWS.Server.Wait (AWS.Server.Q_Key_Pressed);&lt;br/&gt;   AWS.Server.Shutdown (WS);&lt;br/&gt;end Server;&lt;br/&gt;&lt;/pre&gt;
&lt;p&gt;This sets up a new web server and declares that the method Echo in the file ServerCallback.adb will handle our HTTP requests.  The .EXE will run until you hit the Q key.  It will listen, by default, on port 8080.&lt;/p&gt;
&lt;p&gt;9) Define the server callback files &amp;#8220;ServerCallback.adb&amp;#8221; and &amp;#8220;ServerCallback.ads&amp;#8221;.&lt;/p&gt;
&lt;pre&gt;ServerCallback.adb:&lt;br/&gt;&lt;br/&gt;with Templates_Parser;                       use Templates_Parser;&lt;br/&gt;with Templates_Parser.Utils;                 use Templates_Parser.Utils;&lt;br/&gt;with Ada.Strings.Unbounded;                  use Ada.Strings.Unbounded;&lt;br/&gt;&lt;br/&gt;package body ServerCallback is&lt;br/&gt;   function Echo (Request : AWS.Status.Data) return AWS.Response.Data is&lt;br/&gt;      pragma Unreferenced (Request);&lt;br/&gt;      URI : constant String := AWS.Status.URI (Request);&lt;br/&gt;      Params : constant Translate_Table := (1 =&amp;gt; Assoc("URI", URI));&lt;br/&gt;      Response : Unbounded_String;&lt;br/&gt;   begin&lt;br/&gt;      Response := Parse (Utils.Get_Program_Directory &amp;amp; ".." &amp;amp; Directory_Separator&amp;amp; "site.thtml", Params);&lt;br/&gt;      return AWS.Response.Build ("text/html", Response);&lt;br/&gt;   end Echo;&lt;br/&gt;end ServerCallback;&lt;br/&gt;&lt;br/&gt;ServerCallback.ads:&lt;br/&gt;&lt;br/&gt;with AWS.Response;&lt;br/&gt;with AWS.Status;&lt;br/&gt;&lt;br/&gt;package ServerCallback is&lt;br/&gt;   function Echo (Request : AWS.Status.Data) return AWS.Response.Data;&lt;br/&gt;end ServerCallback;&lt;br/&gt;&lt;br/&gt;&lt;/pre&gt;
&lt;p&gt;This loads a template file called site.thtml and passes in a parameter URI which gets resolves to the request URI.  The parameters are passed to the template_parser using TranslateTable or TranslateSet (I used TranslateTable because I knew in advance how many parameters I would have.)&lt;/p&gt;
&lt;p&gt;The actual template itself I put in the root folder of the project (&amp;#8220;..&amp;#8221; from the obj_debug folder that server.exe gets deposited in.)  It&amp;#8217;s basically html with tag declarations that the template_parser replaces with the parameters you supplied above.&lt;/p&gt;
&lt;pre&gt;site.thtml:&lt;br/&gt;&lt;br/&gt;&amp;lt;html&amp;gt;&lt;br/&gt;&amp;lt;body&amp;gt;&lt;br/&gt;Hello from &lt;strong&gt;@_URI_@&lt;/strong&gt;.&lt;br/&gt;&amp;lt;/body&amp;gt;&lt;br/&gt;&amp;lt;/html&amp;gt;&lt;br/&gt;&lt;/pre&gt;
&lt;p&gt;Now you can hit http://localhost:8080/whatever and you should see the response echo the URI you provided.&lt;/p&gt;
&lt;p&gt;You might be wondering how the same program would look in Ruby. Well, like this (assuming you have Ruby and the Sintra gem installed):&lt;/p&gt;
&lt;pre&gt;require 'rubygems'&lt;br/&gt;require 'sinatra'&lt;br/&gt;&lt;br/&gt;get '*' do&lt;br/&gt;  "Hello from &lt;strong&gt;#{params[:splat]}&lt;/strong&gt;"&lt;br/&gt;end&lt;br/&gt;&lt;/pre&gt;
&lt;p&gt;But that&amp;#8217;s nowhere near as fun.&lt;/p&gt;
&lt;p&gt;(Of course, Ada isn&amp;#8217;t really a language intended for web programming.  And I don&amp;#8217;t think I would feel comfortable in an airplane where the fly-by-wire controls were powered by the Ruby VM and the software cobbled together by splicing together features from a half dozen open source gems.)&lt;/p&gt;</description><link>http://www.lmcalpin.com/post/1243213615</link><guid>http://www.lmcalpin.com/post/1243213615</guid><pubDate>Mon, 04 Oct 2010 13:05:00 -0400</pubDate><category>ada</category><category>ruby</category><category>sinatra</category></item><item><title>devise 1.3.3, rails 3 #fail</title><description>&lt;p&gt;I&amp;#8217;m starting a small Rails project for a webapp that I hope to have ready by January.  While working on building up the application&amp;#8217;s foundation, I ran into a small  compatibility issue with Devise and Rails 3.&lt;/p&gt;
&lt;p&gt;Devise 1.3.3 and Rails 3.0, on my Windows development machine at least, seems to have some kind of issue where the helpers don&amp;#8217;t become available.  authenticate_user!, user_signed_in?, current_user, and user_session were unavailable to controllers or views.  Backing out to Devise 1.3.2 did the trick, everything works fine now.&lt;/p&gt;</description><link>http://www.lmcalpin.com/post/1236922238</link><guid>http://www.lmcalpin.com/post/1236922238</guid><pubDate>Sun, 03 Oct 2010 14:57:00 -0400</pubDate><category>rails</category><category>ruby</category></item><item><title>generating ddl with hibernate, envers, and spring</title><description>&lt;p&gt;So I have this Spring app that uses Hibernate and I&amp;#8217;ve defined my model.  And I want to generate the DDL that I need to run to get the database in sync with my model.  I also want to get the DDL for tables needed for use with the Envers auditing framework. Here&amp;#8217;s how you get all that:&lt;/p&gt;
&lt;pre class="source"&gt;@Autowired&lt;br/&gt;LocalContainerEntityManagerFactoryBean lcemfb;&lt;br/&gt;&lt;br/&gt;public void printUpdateScripts() {&lt;br/&gt;	Ejb3Configuration ejb3 = new Ejb3Configuration();&lt;br/&gt;	ejb3.configure(lcemfb.getPersistenceUnitInfo(),&lt;br/&gt;			lcemfb.getJpaPropertyMap());&lt;br/&gt;	Configuration config = ejb3.getHibernateConfiguration();&lt;br/&gt;	config.buildMappings();&lt;br/&gt;	AuditConfiguration.getFor(config); // include audit tables&lt;br/&gt;	Dialect dialect = Dialect.getDialect(config.getProperties());&lt;br/&gt;	DatabaseMetadata metadata;&lt;br/&gt;	Connection conn = null;&lt;br/&gt;	try {&lt;br/&gt;		EntityManager em = lcemfb.getObject().createEntityManager();&lt;br/&gt;		conn = ((HibernateEntityManager) em).getSession().connection();&lt;br/&gt;		metadata = new DatabaseMetadata(conn, dialect);&lt;br/&gt;		String[] scripts = config.generateSchemaUpdateScript(dialect,&lt;br/&gt;				metadata);&lt;br/&gt;		// String[] scripts = config.generateSchemaCreationScript(dialect);&lt;br/&gt;		// String[] scripts = config.generateDropSchemaScript(dialect);&lt;br/&gt;		for (String script : scripts) {&lt;br/&gt;			System.out.println(script);&lt;br/&gt;		}&lt;br/&gt;	} catch (Throwable t) {&lt;br/&gt;		t.printStackTrace();&lt;br/&gt;	} finally {&lt;br/&gt;		if (conn != null) {&lt;br/&gt;			try {&lt;br/&gt;				conn.close();&lt;br/&gt;			} catch (Throwable t) {&lt;br/&gt;				t.printStackTrace();&lt;br/&gt;			}&lt;br/&gt;		}&lt;br/&gt;	}&lt;br/&gt;}&lt;br/&gt;&lt;/pre&gt;
&lt;p&gt;And &lt;a href="http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/orm/jpa/LocalContainerEntityManagerFactoryBean.html"&gt;LocalContainerEntityManagerFactoryBean&lt;/a&gt; is just your standard Spring FactoryBean for creating EntityManagerFactory instances.&lt;/p&gt;
&lt;pre class="source"&gt;&amp;lt;bean id="lcemfb" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"&amp;gt;&lt;br/&gt; &amp;lt;property name="persistenceUnitName" value="..." /&amp;gt;&lt;br/&gt; &amp;lt;property name="dataSource" ref="..." /&amp;gt;&lt;br/&gt; &amp;lt;property name="jpaVendorAdapter" ref="..." /&amp;gt;&lt;br/&gt;&amp;lt;/bean&amp;gt;&lt;br/&gt;&lt;/pre&gt;</description><link>http://www.lmcalpin.com/post/1222094377</link><guid>http://www.lmcalpin.com/post/1222094377</guid><pubDate>Fri, 01 Oct 2010 10:56:00 -0400</pubDate><category>java</category><category>hibernate</category><category>spring</category><category>envers</category></item><item><title>#playframework, #scala, #siena, #gae fun</title><description>&lt;p&gt;In my &lt;a href="http://www.lmcalpin.com/post/1211803505/play-ing-with-scala"&gt;last post&lt;/a&gt;, I mentioned that I created a simple (&lt;em&gt;very simple!&lt;/em&gt;) Google App Engine hosted Play! webapp, written using Scala.  The webapp simply tracks people who visit my blog.  More accurately, it tracks people who view a little PNG that one of the methods renders.  If someone GETs the image, I capture the visitor&amp;#8217;s IP address and the time.  This won&amp;#8217;t be replacing anyone&amp;#8217;s use of Google Analytics anytime soon, I can assure you.&lt;/p&gt;
&lt;p&gt;But for the edification of those who may want to play with Play! and Scala, this is what I did:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;using Play! 1.1, create a new module: play new &amp;#8212;with=scala&lt;/li&gt;
&lt;li&gt;also add siena and gae to your application.conf&lt;/li&gt;
&lt;li&gt;define the paths in your controller.  I just have two, the root path lists the recent visitors, and &amp;#8220;/track&amp;#8221; which renders the image and captures the visitor&amp;#8217;s information.&lt;/li&gt;
&lt;/ul&gt;&lt;pre class="source"&gt;controllers.scala:&lt;br/&gt;&lt;br/&gt;def index {&lt;br/&gt;     val visits = Visit.recent&lt;br/&gt;     render(visits)&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;def track {&lt;br/&gt;     val trackedIP = new Visit&lt;br/&gt;     trackedIP.remoteAddress = request.remoteAddress&lt;br/&gt;     trackedIP.referer = request.headers.getOrElse("referer", None)&lt;br/&gt;     // store it in The Cloud(tm)&lt;br/&gt;     trackedIP.insert()&lt;br/&gt;     // this is the image they see&lt;br/&gt;     val file = Play.getFile("/public/images/favicon.png")&lt;br/&gt;     renderBinary(file)&lt;br/&gt;}&lt;br/&gt;&lt;/pre&gt;
&lt;p&gt;Note the &amp;#8220;getOrElse&amp;#8221; call above. This is one of the nice features of Scala. This is there because request.headers is a Map and the referer key isn&amp;#8217;t guaranteed to be there. In Java, we would do this:&lt;/p&gt;
&lt;pre class="source"&gt;Http.Header refererHeader = request.headers.get("referer");&lt;br/&gt;String referer = "";&lt;br/&gt;if (refererHeader != null) {&lt;br/&gt;    referer = refererHeader.toString();&lt;br/&gt;}&lt;br/&gt;trackedIP.referer = referer;&lt;br/&gt;&lt;/pre&gt;
&lt;p&gt;That&amp;#8217;s quite a mouthful, and the Scala version is much more readable.&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;now, define the model.  Because we are deploying to Google App Engine, we will use the Siena module as Siena works much more naturally with that type of datastore than Hibernate.  I&amp;#8217;ve never been able to get JPA with Hibernate to work on Google App Engine anyway.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;The Visit class extends siena.Model and declares the properties that we will store on the database. The Visit object is a singleton; if we were writing a Java object, the static/class methods we put on the Visit.class are what we are putting in the Visit object here.  In our case, we simply create a method &amp;#8220;recent&amp;#8221; which returns up to 20 of the most recent visitors. The @Index on the date field is necessary so Siena can order by date, which we will do in reverse order (because we want the most RECENT visitors.)&lt;/p&gt;
&lt;pre class="source"&gt;models.scala:&lt;br/&gt;&lt;br/&gt;import play._&lt;br/&gt;import play.data.validation._&lt;br/&gt;import siena._&lt;br/&gt;import java.util.Date&lt;br/&gt;&lt;br/&gt;class Visit extends Model {&lt;br/&gt;     @Id var id:Long = _&lt;br/&gt;     var remoteAddress : String = _&lt;br/&gt;     var referer: String = _&lt;br/&gt;     @Index(Array("date_index")) var date : Date = new Date&lt;br/&gt;}&lt;br/&gt;&lt;br/&gt;object Visit {&lt;br/&gt;     def recent:java.util.List[Visit] = Model.all(classOf[Visit]).order("-date").fetch(20)&lt;br/&gt;}&lt;br/&gt;&lt;/pre&gt;
&lt;p&gt;Your views are done in the same manner that you would do them in a Java-based Play! application: via Groovy templates.  Of course, you can always replace the template engine with Scalate or whatever else you prefer, via Play! plugins.&lt;/p&gt;
&lt;p&gt;One handy trick I learned was the use of the JavaConversions helper class, introduced in Scala 2.8, which adds some implicit conversions between Java and Scala collections classes. This way, if you want to process the result of our call to Visit.recent using Scala style closures, you could do this:&lt;/p&gt;
&lt;pre class="source"&gt;import scala.collection.JavaConversions._&lt;br/&gt;&lt;br/&gt;Visit.recent.foreach(v =&amp;gt; println(v.remoteAddress))&lt;br/&gt;&lt;/pre&gt;
&lt;p&gt;This isn&amp;#8217;t the most useful application, but it does provide a nice starting point for toying with the language.&lt;/p&gt;</description><link>http://www.lmcalpin.com/post/1216678445</link><guid>http://www.lmcalpin.com/post/1216678445</guid><pubDate>Thu, 30 Sep 2010 14:44:00 -0400</pubDate><category>scala</category><category>playframework</category></item></channel></rss>

