<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-8144054433403215910</id><updated>2011-10-01T12:38:08.503-07:00</updated><category term='rhino javascript jsunit'/><category term='osgi obr'/><category term='maven2 maven jflex vt100 ansi'/><category term='bbs twitter un-marketing'/><category term='maven maven2 mavenfail maventrap'/><category term='gwt javascript rhino ssjs'/><title type='text'>Java and then some</title><subtitle type='html'>Exploring mostly Java coding with bits of OSGi, Struts 2, Maven, server-side JavaScript, and then some.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://mrdonbrown.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8144054433403215910/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://mrdonbrown.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Don Brown</name><uri>http://www.blogger.com/profile/01122561628983983736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>8</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8144054433403215910.post-6171077170361138903</id><published>2010-12-11T04:23:00.000-08:00</published><updated>2010-12-11T05:27:20.114-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='bbs twitter un-marketing'/><title type='text'>It's about the relationship, stupid</title><content type='html'>Every year or so, I am overwhelmed by nostalgia for the &lt;a href="http://en.wikipedia.org/wiki/Bulletin_board_system"&gt;B&lt;/a&gt;&lt;a href="http://en.wikipedia.org/wiki/Bulletin_board_system"&gt;BS days&lt;/a&gt; and start playing a &lt;a href="http://tradewars.com/"&gt;TradeWars 2002&lt;/a&gt; game (yes, they still exist).  I don't stop to think why those ANSI text days were better than the current webiness I enjoy today, but while reading this &lt;a href="http://www.un-marketing.com/blog/"&gt;Un-Marketing&lt;/a&gt; book, it hit me - it's about the relationship, stupid.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_YveEdh2jinQ/TQN7M7p0-OI/AAAAAAAAABw/Kv0iYk-Bc2s/s1600/atd_lr9t.gif"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 138px;" src="http://1.bp.blogspot.com/_YveEdh2jinQ/TQN7M7p0-OI/AAAAAAAAABw/Kv0iYk-Bc2s/s320/atd_lr9t.gif" alt="" id="BLOGGER_PHOTO_ID_5549414627952359650" border="0" /&gt;&lt;/a&gt;Back in the "good old days", you dialed into some local guy's computer, tying up your your line and his.  There was no anonymous access, so you had to sign up.  Usually, this sign up process asked more than your name and phone, but forced you to fill out a quick survey about yourself, or in some cases, write an essay on why you should be allowed access.  In several cases, I had ensure my phone number was correct, as the sysop would try to call it, usually within minutes, to verify I existed and have a little chat.  The relationship had begun.&lt;br /&gt;&lt;br /&gt;From then on, connecting to that BBS was as much a social event as anything.  Sure, there were single player games and files to leach or even fidonet-backed "global" discussion groups, but the real fun I found was in the multiplayer games and local discussion groups.  Some boards would have real life meetups, where you get to meet that guy who kept podding your CT (TradeWars thing).&lt;br /&gt;&lt;br /&gt;The icing on the cake was the sysop chat.   At any time, the&lt;a href="http://3.bp.blogspot.com/_YveEdh2jinQ/TQN5h_mGZsI/AAAAAAAAABY/OZXgNFH8CBA/s1600/bbs.png"&gt;&lt;img style="float: right; margin: 0pt 0pt 10px 10px; cursor: pointer; width: 200px; height: 59px;" src="http://3.bp.blogspot.com/_YveEdh2jinQ/TQN5h_mGZsI/AAAAAAAAABY/OZXgNFH8CBA/s200/bbs.png" alt="" id="BLOGGER_PHOTO_ID_5549412790764463810" border="0" /&gt;&lt;/a&gt; sysop could decide to be friendly and interrupt whatever you were doing to start chatting.    Of course, you could call him as well, resulting in a physical ringing on his end.  Not only was it usually the only sort of live chat boards offered, but doing it with the guy who ran the board on which you were dependent gave it extra value.  Some times, the chats were simply to tell you he needed to shut down the board to reboot the computer or that he needed the line for something else.  Other times, he just wanted to be friendly and find out more information about you.  There is nothing like that surge of adrenaline when your screen blanked and then informed you the sysop wanted to chat.&lt;br /&gt;&lt;br /&gt;His powers could go even further.  Once, after uploading a rather naughty Trojan horse containing code to give our TradeWars characters billions of dollars (ended up crashing the game right after we logged in, actually), the sysop was so pissed that when we tried to log in next, he kept hitting the backspace key when we tried to type in our login name.  It goes to show, BBSing was about the relationship between a user and other users, but primarily for me, between the user and the sysop.  The sysop was g*d.  If pissed that guy off, he'd likely tell the other 5 or so boards in your area, and you'd immediately have no access to anything.&lt;br /&gt;&lt;br /&gt;With the Web, it feels like that extra relational dimension just isn't there, or at least it isn't forced on you as it was in the BBS days.  I suppose there is social sites like Facebook, Twitter, and Reddit, but it just isn't the same.   That said, it is likely better and I'm just being a curmudgeon for not putting myself out there and giving it a proper go.  Maybe I should stop muttering about how Twitter has nothing on IRC, and start tweeting every day.  Or not. :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8144054433403215910-6171077170361138903?l=mrdonbrown.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mrdonbrown.blogspot.com/feeds/6171077170361138903/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mrdonbrown.blogspot.com/2010/12/its-about-relationship-stupid.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8144054433403215910/posts/default/6171077170361138903'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8144054433403215910/posts/default/6171077170361138903'/><link rel='alternate' type='text/html' href='http://mrdonbrown.blogspot.com/2010/12/its-about-relationship-stupid.html' title='It&apos;s about the relationship, stupid'/><author><name>Don Brown</name><uri>http://www.blogger.com/profile/01122561628983983736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_YveEdh2jinQ/TQN7M7p0-OI/AAAAAAAAABw/Kv0iYk-Bc2s/s72-c/atd_lr9t.gif' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8144054433403215910.post-3521049177476485751</id><published>2009-09-27T02:09:00.000-07:00</published><updated>2009-09-29T07:07:45.579-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='maven maven2 mavenfail maventrap'/><title type='text'>Introducing Maven Trap - the honey pot for Maven malcontents</title><content type='html'>For far too many years, Maven 2 has dominated my builds, and I've sat idly by, taking what they've given, meekly replying, "Thank you sir, can I have some more?"  I've watched my builds break apart on unmodified code or just hang, I've nearly drown fighting the torrent of jumbled output trying to find the lone test failure, and I've lost my sanity wading through huge XML build files trying to understand why my build is downloading the internet.  &lt;br /&gt;&lt;br /&gt;Sure, there have been moments of resistance, like when&lt;a href="http://www.jroller.com/mrdon/entry/making_maven_2_not_suck"&gt; I created a fork of Maven&lt;/a&gt; to add features like parallel downloading of artifacts, but the effort in maintaining a fork is too high when, honestly, I'd rather be doing just about anything than hacking build systems.  Still, the revolutionary fire never died, despite not having a sustainable outlet.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_YveEdh2jinQ/Sr9KQ3_ZDsI/AAAAAAAAAAk/dMm2YUCI4AI/s1600-h/Circus_Lion_Tamer.jpg"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 200px; height: 152px;" src="http://2.bp.blogspot.com/_YveEdh2jinQ/Sr9KQ3_ZDsI/AAAAAAAAAAk/dMm2YUCI4AI/s200/Circus_Lion_Tamer.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5386105333126598338" /&gt;&lt;/a&gt;&lt;br /&gt;Like the scrappy fighter that keeps bouncing back after a huge left hook, I'm back, but this time, looking for victory by treating Maven like the unpredictable wild animal it can be.  Instead of forking Maven, a fellow Atlassian Sam Le Berrigaud and I have put it in its cage by wrapping the executable with an interceptor framework, allowing modules to control how Maven gets executed and what happens after it gives up the ghost.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://github.com/mrdon/maven-trap"&gt;Maven Trap&lt;/a&gt; is this executable interception framework and three modules:&lt;ul&gt;&lt;li&gt;&lt;b&gt;Console Colorization&lt;/b&gt; - Pages of white or green text is hard to read and makes it easy for critical errors to slip by.  This module transforms output into ANSI colorized text to make it easier to see errors and other key events.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;Always Offline&lt;/b&gt; - A build system should not connect the network unless you explicitly give it permission.  This module inverts the meaning of the "-o" flag to make the default offline, only to be enabled via the "-o" flag.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;YAML POM&lt;/b&gt; - While XML is great for programs, it sucks for humans.  This module automatically converts your XML pom.xml file into a YAML-formatted pom.yml for either read-only or editable usage.&lt;/li&gt;&lt;/ul&gt;Since Maven Trap treats Maven as an opaque black box, what it can do is limited, however, it provides low-risk integration points that can be extended fairly easily and should work with most any version of Maven.  Each module can be enabled by setting a unique environment variable, giving you full control over which features you want without modifying your Maven installation.&lt;br /&gt;&lt;br /&gt;No announcement is complete without a screenshot, so here is all three modules enabled on simple project:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_YveEdh2jinQ/Sr8ztM4sPlI/AAAAAAAAAAc/mAQF0S2BtUE/s1600-h/maven-trap.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 314px; height: 320px;" src="http://2.bp.blogspot.com/_YveEdh2jinQ/Sr8ztM4sPlI/AAAAAAAAAAc/mAQF0S2BtUE/s320/maven-trap.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5386080531004538450" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;We use this in the &lt;a href="http://confluence.atlassian.com/display/DEVNET/How+to+Build+an+Atlassian+Plugin+using+the+Atlassian+Plugin+SDK"&gt;Atlassian Plugin SDK&lt;/a&gt;, as we include our own customized installation of Maven to try to reduce the Maven hassles that our development community continually faces.  If you too are fed up with how Maven is always accessing the internet, produces heaps of unmanageable output, or uses obtuse XML configuration, give Maven Trap a go, or better yet, join GitHub and fork it for full control.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8144054433403215910-3521049177476485751?l=mrdonbrown.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mrdonbrown.blogspot.com/feeds/3521049177476485751/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mrdonbrown.blogspot.com/2009/09/introducing-maven-trap-honey-pot-for.html#comment-form' title='18 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8144054433403215910/posts/default/3521049177476485751'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8144054433403215910/posts/default/3521049177476485751'/><link rel='alternate' type='text/html' href='http://mrdonbrown.blogspot.com/2009/09/introducing-maven-trap-honey-pot-for.html' title='Introducing Maven Trap - the honey pot for Maven malcontents'/><author><name>Don Brown</name><uri>http://www.blogger.com/profile/01122561628983983736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_YveEdh2jinQ/Sr9KQ3_ZDsI/AAAAAAAAAAk/dMm2YUCI4AI/s72-c/Circus_Lion_Tamer.jpg' height='72' width='72'/><thr:total>18</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8144054433403215910.post-4608088776891023077</id><published>2009-09-24T08:44:00.001-07:00</published><updated>2009-09-24T09:36:24.617-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rhino javascript jsunit'/><title type='text'>Better server-side JavaScript unit testing</title><content type='html'>As part of a project aiming at a server and client-side tag library based Rhino, I thought it might be nice to write my unit tests in JavaScript.  A quick Google search later and I find the non-uniquely named &lt;a href="http://jsunit.berlios.de/"&gt;JsUnit&lt;/a&gt; project, which not only implements *unit in JavaScript, but has Ant and Maven 2 support.  However, quite soon, I hit some problems, mainly around very little error reporting and feedback.  Few things are as annoying as knowing there is a problem, but having no idea where.&lt;br /&gt;&lt;br /&gt;A quick &lt;a href="http://github.com/mrdon/jsunit"&gt;fork&lt;/a&gt; later and I now have JsUnit 1.3-db.  So far, this fork adds:&lt;br /&gt;* Callstack reporting for errors and failures&lt;br /&gt;* Text test result output, not just XML&lt;br /&gt;* File and line numbers in all error messages&lt;br /&gt;* Upgraded Rhino&lt;br /&gt;&lt;br /&gt;Previously, if you hit an error, you'd get this:&lt;pre&gt;[INFO] [jsunit2:jsunit-test {execution: test}]&lt;br /&gt;[INFO] ------------------------------------------------------------------------&lt;br /&gt;[ERROR] BUILD FAILURE&lt;/pre&gt;Then, you'd have to dig into the &lt;code&gt;target/surefire-reports/TEST-MyTestCase.xml&lt;/code&gt; to find this:&lt;br /&gt;&lt;pre&gt;&amp;lt;testcase name="TestFieldTest.testRender" time="0.006"&gt;&lt;br /&gt;   &amp;lt;error message="ReferenceError: "bar" is not defined." type=""/&gt;&lt;br /&gt; &amp;lt;/testcase&gt;&lt;/pre&gt;Not helpful.  Now, you get this:&lt;pre&gt;[INFO] [jsunit2:jsunit-test {execution: test}]&lt;br /&gt;TestRunner (1 test cases available)&lt;br /&gt;&gt; Starting test suite "TextFieldTest"&lt;br /&gt;- Running test 1: "TextFieldTest.testRender"&lt;br /&gt;ERROR in TextFieldTest.testRender: ReferenceError: "bar" is not defined. (TextField.js:7)&lt;br /&gt;&lt;br /&gt;Stack trace: &lt;br /&gt;1: TextField.js:7&lt;br /&gt;2: TextFieldTest.js:6 (TextFieldTest_testRender)&lt;br /&gt;3: JsUnit.js:827 (TestCase_runTest)&lt;br /&gt;4: JsUnit.js:808 (TestCase_runBare)&lt;br /&gt;5: JsUnit.js:386&lt;br /&gt;6: JsUnit.js:409 (TestResult_runProtected)&lt;br /&gt;7: JsUnit.js:390 (TestResult_run)&lt;br /&gt;8: JsUnit.js:797 (TestCase_run)&lt;br /&gt;9: JsUnit.js:1033 (TestSuite_runTest)&lt;br /&gt;10: JsUnit.js:1014 (TestSuite_run)&lt;br /&gt;11: JsUnit.js:2614 (EmbeddedTextTestRunner_run)&lt;br /&gt;12: Components:4&lt;br /&gt;&lt; Completed test suite "TextFieldTest"&lt;br /&gt;1 error, 0 failures.&lt;br /&gt;[INFO] ------------------------------------------------------------------------&lt;br /&gt;[ERROR] BUILD FAILURE&lt;/pre&gt;For fellow Maven folks, you can find the releases at my repo: &lt;br /&gt;&lt;a href=" http://twdata-m2-repository.googlecode.com/svn/de/berlios/jsunit/jsunit-maven2-plugin"&gt;&lt;br /&gt;http://twdata-m2-repository.googlecode.com/svn/de/berlios/jsunit/jsunit-maven2-plugin&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8144054433403215910-4608088776891023077?l=mrdonbrown.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mrdonbrown.blogspot.com/feeds/4608088776891023077/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mrdonbrown.blogspot.com/2009/09/better-server-side-javascript-unit.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8144054433403215910/posts/default/4608088776891023077'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8144054433403215910/posts/default/4608088776891023077'/><link rel='alternate' type='text/html' href='http://mrdonbrown.blogspot.com/2009/09/better-server-side-javascript-unit.html' title='Better server-side JavaScript unit testing'/><author><name>Don Brown</name><uri>http://www.blogger.com/profile/01122561628983983736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8144054433403215910.post-8630944838605277948</id><published>2009-09-05T21:19:00.000-07:00</published><updated>2009-09-05T22:37:33.626-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='gwt javascript rhino ssjs'/><title type='text'>GWT for JavaScript Junkies</title><content type='html'>The most appealing thing about GWT for me isn't the fact that I, as a Java developer, don't have to write JavaScript anymore (hey, I like JavaScript!), but the single development experience.  Since everything is in Java, you can have common libraries, coding patterns, frameworks, and editor behavior, drastically simplifying the development experience.  My second favorite aspect of GWT is its component library.  For far too long, we Java developers have treated HTML as just text to output, which is like treating programming as a series of ones and zeros - surely we can work at a higher level than that.&lt;br /&gt;&lt;br /&gt;Therefore, I set out to explore what it would be like to have a GWT-like development experience for JavaScript developers, only instead of Java everywhere, you write JavaScript.  Also, I wanted the bulk of the UI to be built on the server-side to minimize XHR calls and improve accessibility.  To implement the server-side component library, I ripped of as much of Apache Wicket as I could, while keeping it 100% stateless (no session usage or complicated state sharing schemes).  I'm not sure how to package this yet (new framework, Struts 2 plugin, require OSGi, or whatever), but before I go too far down the road of making it a proper framework, I thought I'd get some feedback on the basic design.&lt;br /&gt;&lt;br /&gt;This is what the code of a simple application looks like:&lt;br /&gt;&lt;pre&gt;/controllers/comment.js&lt;br /&gt;/templates/comment/comment.html&lt;br /&gt;&lt;/pre&gt;&lt;h4&gt;comment.html&lt;/h4&gt;The comment.html template is a simple HTML page with "jsid" attribute markers to determine where the components are rendered.  Absolutely no logic is allowed in a template:&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;html&amp;gt;&lt;br /&gt;  &amp;lt;head&amp;gt;&lt;br /&gt;    // import jquery and json&lt;br /&gt;  &amp;lt;/head&amp;gt;&lt;br /&gt;  &amp;lt;body&amp;gt;&lt;br /&gt;    &amp;lt;form jsid="commentForm" action="#"&amp;gt;&lt;br /&gt;      &amp;lt;input jsid="title" type="text"&amp;gt;&lt;br /&gt;      &amp;lt;input jsid="body" type="text"&amp;gt;&lt;br /&gt;      &amp;lt;input jsid="submit" value="Submit" type="submit"&amp;gt;&lt;br /&gt;    &amp;lt;/form&amp;gt;&lt;br /&gt;    &amp;lt;script type="text/javascript" jsid="proxies"&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;  &amp;lt;body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;h4&gt;comment.js&lt;/h4&gt;Where it gets interesting is in comments.js.  This follows the basic design of Ruby on Rails controllers with some interesting twists:&lt;br /&gt;&lt;pre name="code" class="js"&gt;page({&lt;br /&gt;comment : function(params) {&lt;br /&gt;   this.commentForm = new Form();&lt;br /&gt;   this.commentForm.add(new TextField("title"));&lt;br /&gt;&lt;br /&gt;   var body = new TextField("body", {&lt;br /&gt;       value : "Great feature",&lt;br /&gt;       label : "Body",&lt;br /&gt;       description : "The body of the comment"&lt;br /&gt;   });&lt;br /&gt;   this.commentForm.add(body);&lt;br /&gt;   this.commentForm.add(new Submit("submit"));&lt;br /&gt;&lt;br /&gt;   this.commentForm.onsubmit = function() {&lt;br /&gt;       alert('calling comment');&lt;br /&gt;       saveComment({&lt;br /&gt;           title : jQuery('#title').val(),&lt;br /&gt;           body  : jQuery('#body').val()&lt;br /&gt;       }, function() {&lt;br /&gt;           alert("Comment saved");&lt;br /&gt;       });&lt;br /&gt;       return false;&lt;br /&gt;   }.toString();&lt;br /&gt;&lt;br /&gt;   this.proxies = new Proxies(['saveComment']);&lt;br /&gt;},&lt;br /&gt;saveComment : function(comment) {&lt;br /&gt;   print("comment title: " + comment.title + " body: " + comment.body);&lt;br /&gt;   this.result = "success";&lt;br /&gt;}&lt;br /&gt;});&lt;br /&gt;&lt;/pre&gt;Ok, starting from the top.  You pass into the "page" function a map of methods to be used as controller methods, although there is a mix of HTML and JSON-producing methods: "comment" returns a comment page, while "saveComment" is a JSON-invokable method.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;comment()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Since this is the method that will render HTML, we will build up our component tree.  Instance variables like 'commentForm' are the first to be matched against comment.html, with subcomponents matching accordingly as the template processor works its way through the HTML.  There are four components used in this page:&lt;ol&gt;&lt;li&gt;"Form" - represents an HTML form&lt;/li&gt;&lt;li&gt;"TextField" - represents an HTML text input field&lt;/li&gt;&lt;li&gt;"Submit" - represents a submit button&lt;/li&gt;&lt;li&gt;"Proxies" - generates client-side proxy methods that call the corresponding server-side ones&lt;/li&gt;&lt;/ol&gt;The main advantage of building your components in server-side code and not in a template is the much greater options you have for presentation logic.  In this example, I just use hard-coded strings, but you can see how these could just as easily be initialized using service calls.&lt;br /&gt;&lt;br /&gt;Nothing eye-opening so far...until you get down to the onsubmit() method.  What we are doing is creating a method that will be executed on the client-side in our server-side code, using the nifty toString() feature on functions to get the source.  We could have just as easily wrote it in a big string, but this way we get better editor support and fail-fast parser failure reporting.  This also serves to help "blur" the line between server and client-side code ala GWT.&lt;br /&gt;&lt;br /&gt;Finally, we create the "Proxies" component, passing the server-side function names that we want to be able call from the client.  My implementation uses JQuery and JSON to stringify objects, but those details are irrelevant here.  The point is we are able to call "saveComment()" on the client-side as if it was on the server-side, with all the json parsing and construction happening behind the scenes.  Since both sides are JavaScript, you don't have the immedience mismatch you do in other languages.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;saveComment&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The "saveComment()" function is a remotely executable function, meant to receive and return JSON, although you aren't limited to it.  JSON in the request body is generally a good idea since it limits your vulnerability to cross-domain request forgery.  Of course, this technique also means your form only works with JavaScript turned on, which may not be an option.  The "comment" argument is the serialized object passed from the client, and we return a serialized instance of our controller, which is why we set the result by setting the instance variable.&lt;br /&gt;&lt;br /&gt;This basically completes the tutorial.  One other thing to note is the components are also written in JavaScript, and since that means Rhino, you get all the E4X niceities in constructing HTML.  This means even the HTML is syntaxally processed when the script is loaded.&lt;h4&gt;Next steps&lt;/h4&gt;My next step is to build a real application using this little framework and see how it scales as the feature demands pile on.  Thanks to Rhino, I can keep developing the backend of this application in Java with all the libraries and frameworks I depend on.  The consistent use of JavaScript for the presentation layer hopefully means less code, more reuse, and more productivity.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8144054433403215910-8630944838605277948?l=mrdonbrown.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mrdonbrown.blogspot.com/feeds/8630944838605277948/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mrdonbrown.blogspot.com/2009/09/gwt-for-javascript-junkies.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8144054433403215910/posts/default/8630944838605277948'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8144054433403215910/posts/default/8630944838605277948'/><link rel='alternate' type='text/html' href='http://mrdonbrown.blogspot.com/2009/09/gwt-for-javascript-junkies.html' title='GWT for JavaScript Junkies'/><author><name>Don Brown</name><uri>http://www.blogger.com/profile/01122561628983983736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8144054433403215910.post-6047977112354285172</id><published>2009-08-18T17:27:00.001-07:00</published><updated>2009-08-18T17:53:22.452-07:00</updated><title type='text'>Playing second fiddle - Java backend for Bespin</title><content type='html'>So I'm the poor sap who decided to take on &lt;a href="http://groups.google.com/group/bespin/browse_thread/thread/44ead8a1d438496"&gt;building a Java backend&lt;/a&gt; for &lt;a href="https://bespin.mozilla.com/"&gt;Bespin&lt;/a&gt;.  Michael Mahemoff &lt;a href="http://softwareas.com/will-bespin-really-end-up-with-multiple-backends"&gt;wonders if Bespin will ever have multiple backends&lt;/a&gt;, and I obviously believe the answer is yes, so I thought I'd go into why I think it is a good idea.&lt;br /&gt;&lt;br /&gt;Bespin represents an opportunity to fundamentally change how we develop software.  It dramatically lowers the barrier of entry to development, ideal for  software modules that are smaller, more focused, and testable.  At this point, it isn't suited to all software development, but for extension systems like a good plugin system that allows small bits of code to be plugged into a system at runtime, I think it is a perfect fit. &lt;br /&gt;&lt;br /&gt;While Java development, for example, can be quite fast once you get all your frameworks, build systems, and IDE's in place, it also be a house of cards that the slightest network or external server-related wind can bring to a tumbling crash.  I'd rather have an application focus on providing a solid platform with accessible API's, then provide a development environment in the app itself to write little plugins.  Then, any developer can log in and get to writing real code without all the setup and build issues.&lt;br /&gt;&lt;br /&gt;Therefore, building an embeddable Java backend is critical since all the web applications that I work on are Java-based.  There are many times I want to write a little plugin, but dealing with Maven 2 and IDEA seems overkill.  Being able to log into a dev server and hack away would dramatically reduce the time from idea to code and make it more likely I'll actually do it and not put it on the "I should do that someday" shelf.&lt;br /&gt;&lt;br /&gt;They say in order to take advantage of your creative potential, you should carry around a notepad to jot down ideas as you have them.  Think of Bespin as a code-able notepad.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8144054433403215910-6047977112354285172?l=mrdonbrown.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mrdonbrown.blogspot.com/feeds/6047977112354285172/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mrdonbrown.blogspot.com/2009/08/playing-second-fiddle-java-backend-for.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8144054433403215910/posts/default/6047977112354285172'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8144054433403215910/posts/default/6047977112354285172'/><link rel='alternate' type='text/html' href='http://mrdonbrown.blogspot.com/2009/08/playing-second-fiddle-java-backend-for.html' title='Playing second fiddle - Java backend for Bespin'/><author><name>Don Brown</name><uri>http://www.blogger.com/profile/01122561628983983736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8144054433403215910.post-3699614897221014982</id><published>2009-07-25T20:07:00.000-07:00</published><updated>2009-07-25T20:31:45.231-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='osgi obr'/><title type='text'>Installing OSGi bundles with dependencies</title><content type='html'>One of my favorite features of OSGi is you can write jars/bundles that provide code and/or services to other jar/bundles.  However, one of my least favorite features of OSGi is how you can't just install a single jar, as most likely, that bundle will require packages and services from other bundles in order to work.  Passing a list of bundles with instructions to install them in a certain order sucks.&lt;br /&gt;&lt;br /&gt;To help solve this deficiency, there is the OSGi Bundle Repository (OBR), which is a bit like Maven 2's dependency management in that when you install a bundle using it, OBR can look at external repositories to find any required dependencies and install them as well.  Unfortunately, a) there is barely any documentation or code samples out there on integrating OBR into your OSGI application and b) having an OSGi app go out to the internet to download other bundles at runtime just plain scares me;  take Maven's penchant for downloading the internet and put that "feature" into your production application... *shudder*.&lt;br /&gt;&lt;br /&gt;The solution I came up with uses the dependency resolution aspect of OBR but without needing any network access.   Instead of installing a bundle directly, you install an ".obr" file, which is a zip file with the following layout:&lt;br /&gt;&lt;pre&gt;main-bundle1.jar&lt;br /&gt;obr.xml&lt;br /&gt;dependencies/dep-bundle.jar&lt;br /&gt;dependencies/dep-bundle2.jar&lt;/pre&gt;&lt;br /&gt;When installed, the installer looks at the obr.xml and determines if the main bundle can be installed as is.  If there are any missing dependencies, it takes them from the "dependencies" directory and installs as necessary.  Therefore, only the necessary bundles are installed yet OBR doesn't go out to the network, and, bottom line, you can again distribute and install one file.&lt;br /&gt;&lt;br /&gt;The obr.xml file is the standard OBR descriptor file that describes the main bundle and all its dependencies.  The dependency bundles are packaged in the .obr zip only to be used if needed during installation.  For example, if user A installs the .obr file on their osgi system that already contains dep-bundle.jar, then the installation process will only install dep-bundle2.jar.  If user B has neither, then the installation process installs both dependency bundles.&lt;br /&gt;&lt;br /&gt;There are other options I found (PAR, DeploymentAdmin) for grouping bundles, however, they tend to exist as a way to define multiple bundles as a single, possibly indivisible, unit, but in our case, dependencies are meant to be shared between bundles of different origins.  Did I miss anything or is this the best option for achieving my goals?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8144054433403215910-3699614897221014982?l=mrdonbrown.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mrdonbrown.blogspot.com/feeds/3699614897221014982/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mrdonbrown.blogspot.com/2009/07/installing-osgi-bundles-with.html#comment-form' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8144054433403215910/posts/default/3699614897221014982'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8144054433403215910/posts/default/3699614897221014982'/><link rel='alternate' type='text/html' href='http://mrdonbrown.blogspot.com/2009/07/installing-osgi-bundles-with.html' title='Installing OSGi bundles with dependencies'/><author><name>Don Brown</name><uri>http://www.blogger.com/profile/01122561628983983736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8144054433403215910.post-7904490768279809138</id><published>2009-07-17T07:24:00.000-07:00</published><updated>2009-07-17T08:03:31.140-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='maven2 maven jflex vt100 ansi'/><title type='text'>Greasemonkey for Maven 2</title><content type='html'>Few things are more tedious than crawling through hundreds of lines of Maven 2 output to discover which test failed, mojo didn't execute correctly, or error was thrown during integration tests.  After using git for my primary version control tool, I'm spoiled with its lovely full-color output, so why can't I have that for Maven 2?&lt;br /&gt;&lt;br /&gt;Turns out, there is a &lt;a href="http://jira.codehaus.org/browse/MNG-3507"&gt;ticket open&lt;/a&gt; in the Maven JIRA project for this, but so far, there doesn't seem much traction, and fixing it for me now would involve forking Maven again, which I'd rather not.  Therefore, I decided to take the Greasemonkey approach and write a wrapper around the Maven output so that I can format it exactly how I want.&lt;br /&gt;&lt;br /&gt;Introducing the &lt;a href="http://github.com/mrdon/console-colorizer/tree/master"&gt;Console Colorizer&lt;/a&gt;, a command line tool for wrapping Maven execution, then feeding its output through a Lexer that adds VT100 color codes where appropriate.  This approach is suprior to the usual colorizing the logging output, because I can match any text and highlight it any way I want.  Going a bit farther, I could even detect certain bits of output and execute arbitrary code, like sending a &lt;a href="http://growl.info/"&gt;Growl&lt;/a&gt; or IM notification.  All this without modifying any Maven Java code.&lt;br /&gt;&lt;br /&gt;Compare this raw Maven 2 output:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_YveEdh2jinQ/SmCMr8jTJ4I/AAAAAAAAAAM/JilXzZIeeAY/s1600-h/output-ugly.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 228px;" src="http://1.bp.blogspot.com/_YveEdh2jinQ/SmCMr8jTJ4I/AAAAAAAAAAM/JilXzZIeeAY/s320/output-ugly.png" alt="" id="BLOGGER_PHOTO_ID_5359438243187337090" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;With this:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_YveEdh2jinQ/SmCM12u93AI/AAAAAAAAAAU/QJlqnCowQuw/s1600-h/output-colorized.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 234px;" src="http://3.bp.blogspot.com/_YveEdh2jinQ/SmCM12u93AI/AAAAAAAAAAU/QJlqnCowQuw/s320/output-colorized.png" alt="" id="BLOGGER_PHOTO_ID_5359438413424352258" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;It is so much easier to see that the test failed, and what warnings your Maven plugins are complaining about.  This tool works by wrapping the Maven main execution and running the System.out through a &lt;a href="http://jflex.de/"&gt;JFlex &lt;/a&gt;lexer.  The lexer is nice because it allows me to define tokens via regular expressions, yet remain very fast and compact.  A few VT100  codes allow me to add the coloring.&lt;br /&gt;&lt;br /&gt;Of course, this same technique could be applied to any Java program, or any program at all if you really wanted to, but for now, I think it'll do nicely to clean up Maven 2 a bit.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8144054433403215910-7904490768279809138?l=mrdonbrown.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mrdonbrown.blogspot.com/feeds/7904490768279809138/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mrdonbrown.blogspot.com/2009/07/greasemonkey-for-maven-2.html#comment-form' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8144054433403215910/posts/default/7904490768279809138'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8144054433403215910/posts/default/7904490768279809138'/><link rel='alternate' type='text/html' href='http://mrdonbrown.blogspot.com/2009/07/greasemonkey-for-maven-2.html' title='Greasemonkey for Maven 2'/><author><name>Don Brown</name><uri>http://www.blogger.com/profile/01122561628983983736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_YveEdh2jinQ/SmCMr8jTJ4I/AAAAAAAAAAM/JilXzZIeeAY/s72-c/output-ugly.png' height='72' width='72'/><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8144054433403215910.post-3367625498703574202</id><published>2009-07-17T07:15:00.000-07:00</published><updated>2009-07-17T07:18:07.318-07:00</updated><title type='text'>Goodbye JRoller</title><content type='html'>After some four or five years, it is time to move off of &lt;a href="http://jroller.com/mrdon"&gt;JRoller&lt;/a&gt;.  That site goes down more often than a...well, you get the point.  Let's see how blogger treats me...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8144054433403215910-3367625498703574202?l=mrdonbrown.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mrdonbrown.blogspot.com/feeds/3367625498703574202/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mrdonbrown.blogspot.com/2009/07/goodbye-jroller.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8144054433403215910/posts/default/3367625498703574202'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8144054433403215910/posts/default/3367625498703574202'/><link rel='alternate' type='text/html' href='http://mrdonbrown.blogspot.com/2009/07/goodbye-jroller.html' title='Goodbye JRoller'/><author><name>Don Brown</name><uri>http://www.blogger.com/profile/01122561628983983736</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry></feed>
