Wednesday, May 29, 2013

6 beeps of death!

My old dell laptop that I bought in December, 2009 has finally reached its pathetic end - the laptop beeps 6 times at boot (video card test failure), then sits there like a lump. It looks like there's no easy fix, so it's time to buy a new laptop. Ugh!

The timing is both good and bad. Good - because my last freelance contract ended a couple weeks ago, so I'm between projects right now, and not having a laptop for a few days forces me to disconnect (or borrow the wife's computer to add to the bLog ...). The timing is bad, because Intel's 4th generation Haswell chips aren't due for release until next week (June 4th) at Computex. Apple's WWDC opens June 10, so I need to wait at least one week to order a Haswell Windows laptop or two weeks for a Haswell Mac.

I still haven't decided exactly how I want to spec out the new box. I know I want at least 8GB RAM and a Core-i5 processor - preferably 4th gen. I'd rather have 128 GB SSD (really 256 GB would be great) than a 556 GB disk, and I prefer an ultrabook (no ethernet, firewire, DVD, whatever - just wireless and ports for USB-3 and display) than a traditional laptop. I think I'd rather have a Mac than Windows this time around - especially since people force Apple to monitor its environment impact and labor conditions in China (I'd be surprised if Lenovo or Asus care about that).

I'd also rather spend $1000 than $1500. I'm not sure if I can satisfy all my constraints! Anyway - I'll wait till next week - hopefully some new systems are released at Computex.

Monday, May 27, 2013

ant rules for typescript compile

I extended littleware's ant template with rules to compile typescript (*.ts) files in web projects using this ant-macro posted on stackoverflow. The typescript and yuidoc rules are listed further below.

Littleware's build system just extends netbeans' ant templates with IVY support. Netbeans' ant scripts are designed to support extension hooks that run before and after the different build stages (initialization, compile, package, ...). This is from the comment at the top of a new netbeans project's build.xml file:


    There exist several targets which are by default empty and which can be 
    used for execution of your tasks. These targets are usually executed 
    before and after some main targets. They are: 

      -pre-init:                 called before initialization of project properties 
      -post-init:                called after initialization of project properties 
      -pre-compile:              called before javac compilation 
      -post-compile:             called after javac compilation 
      -pre-compile-single:       called before javac compilation of single file
      -post-compile-single:      called after javac compilation of single file
      -pre-compile-test:         called before javac compilation of JUnit tests
      -post-compile-test:        called after javac compilation of JUnit tests
      -pre-compile-test-single:  called before javac compilation of single JUnit test
      -post-compile-test-single: called after javac compilation of single JUunit test
      -pre-dist:                 called before archive building 
      -post-dist:                called after archive building 
      -post-clean:               called after cleaning build products 
      -pre-run-deploy:           called before deploying
      -post-run-deploy:          called after deploying

...

Anyway - I'm glad for netbeans' extensible ant templates. Littleware's build system could benefit from another rework to better support scala and IVY, but it's good enough for now.

Finally - I also wanted to mention that Ian Obermiller posted on github a typescript brush for Alex Gorbatchev's syntax highlighter. It seems to work great ...

Here are those ant rules I mentioned earlier ...

<target name="config-check">
     <!--
    <available file="${ivy.jar.dir}/littlesettings.xml" property="settings.exists"/>
    -->
    <available file="${ivy.jar.file}" property="ivyjar.exists"/>
    <condition property="skip.download">
        <and>
            <isset property="ivyjar.exists" />
        </and>
    </condition>
    <available file="ivy/test" property="ivy.resolve.test.exists" />
    <available file="ivy/compile" property="ivy.resolve.compile.exists" />

    ...
    
    <condition property="ivy.resolve.exists">
        <and>
            <isset property="ivy.resolve.test.exists" />
            <isset property="ivy.resolve.compile.exists" />
        </and>
    </condition>
    
    <condition property="typescript.ready">
        <and>
            <isset property="build.web.dir" />
            <isset property="typescript.compiler.path" />
            <available file="${typescript.compiler.path}" />
        </and>
    </condition>    
    
    <condition property="ydoc.ready">
        <and>
            <isset property="build.web.dir" />
            <isset property="ydoc.path" />
            <available file="${ydoc.path}" />
        </and>
    </condition>    
    
</target>

<!-- web project stuff -->

<property name="typescript.compiler.path" value="${user.home}/AppData/Roaming/npm/tsc.cmd" />
<property name="ydoc.path" value="${user.home}/Documents/Code/yuidoc/bin/ydoc.bat" />


<target name="ydoc" depends="config-check" if="ydoc.ready" 
    description="run ydoc on build/ js"
    >
  <exec executable="${ydoc.path}">
    <arg value="${build.web.dir}/resources/js/littleware"/>
 </exec>    
</target>

    
<!--
    Recursively read a source directory for TypeScript files, generate a compile list in the
    format needed by the TypeScript compiler adding every parameters it take.
    Thanks Tekool.net:
       http://stackoverflow.com/questions/12799237/how-to-watch-and-compile-all-typescript-sources
-->
<macrodef name="TypeScriptCompileDir">

    <!-- required attribute -->
    <attribute name="src" />

    <!-- optional attributes -->
    <attribute name="out" default="" />
    <attribute name="module" default="" />
    <attribute name="comments" default="" />
    <attribute name="declarations" default="" />
    <attribute name="nolib" default="" />
    <attribute name="target" default="" />

    <sequential>

        <!-- local properties -->
        <local name="out.arg"/>
        <local name="module.arg"/>
        <local name="comments.arg"/>
        <local name="declarations.arg"/>
        <local name="nolib.arg"/>
        <local name="target.arg"/>
        <local name="typescript.file.list"/>
        <local name="tsc.compile.file"/>

        <property name="tsc.compile.file" value="@{src}compile.list" />

        <!-- Optional arguments are not written to compile file when attributes not set -->
        <condition property="out.arg" value="" else='--out "@{out}"'>
            <equals arg1="@{out}" arg2="" />
        </condition>

        <condition property="module.arg" value="" else="--module @{module}">
            <equals arg1="@{module}" arg2="" />
        </condition>

        <condition property="comments.arg" value="" else="--comments">
            <equals arg1="@{comments}" arg2="" />
        </condition>

        <condition property="declarations.arg" value="" else="--declarations">
            <equals arg1="@{declarations}" arg2="" />
        </condition>

        <condition property="nolib.arg" value="" else="--nolib">
            <equals arg1="@{nolib}" arg2="" />
        </condition>

        <!-- Could have been defaulted to ES3 but let the compiler uses its own default is quite better -->
        <condition property="target.arg" value="" else="--target @{target}">
            <equals arg1="@{target}" arg2="" />
        </condition>

        <!-- Recursively read TypeScript source directory and generate a compile list -->
        <pathconvert property="typescript.file.list" dirsep="\" pathsep="${line.separator}">

            <fileset dir="@{src}">
                <include name="**/*.ts" />
                <exclude name="**/*.d.ts" />
            </fileset>

            <!-- In case regexp doesn't work on your computer, comment <mapper /> and uncomment <regexpmapper /> -->
            <mapper type="regexp" from="^(.*)$" to='"\1"' />
            <!--regexpmapper from="^(.*)$" to='"\1"' /-->

        </pathconvert>


        <!-- Write to the file -->
        <echo message="Writing tsc command line arguments to : ${tsc.compile.file}" />
        <echo file="${tsc.compile.file}" message="${typescript.file.list}${line.separator}${out.arg}${line.separator}${module.arg}${line.separator}${comments.arg}${line.separator}${declarations.arg}${line.separator}${nolib.arg}${line.separator}${target.arg}${line.separator}--sourcemap" append="false" />

        <!-- Compile using the generated compile file --> 
        <echo message="Calling ${typescript.compiler.path} with ${tsc.compile.file}" />
        <exec dir="." executable="${typescript.compiler.path}">
            <arg value="@${tsc.compile.file}"/>
        </exec>

        <!-- Finally delete the compile file 
        <echo message="${tsc.compile.file} deleted" />
        <delete file="${tsc.compile.file}" />
        -->

    </sequential>

</macrodef>


<target name="typescript" depends="config-check" if="typescript.ready" 
    description="compile typescript files build/*.ts"
    >
      <TypeScriptCompileDir
          src="${build.web.dir}/resources/js/"
          module="amd"
      />      
      
    <!-- out="${build.web.dir}/resources/js" -->
</target>


<!-- post-compile rule kicks in if build.web.dir netbeans property is defined -->
<target name="-post-compile" depends="ydoc,typescript" if="build.web.dir">
      <copy todir="${build.web.dir}/WEB-INF/lib">
        <fileset dir="ivy/test"/>
      </copy>
</target>

Sunday, May 26, 2013

YUI modules with Typescript

I finally made time this week to play with typescript - a statically typed javascript extension developed at Microsoft. I like Typescript a lot. I prefer working with statically typed code for most applications, and Typescript also improves on javascript's syntax. I also think Typescript's approach to extending javascript while maintaining direct interoperability with existing javascript code (typescript can call javascript code directly, and vice versa) is better than the "rebuild the universe" strategy taken by dart and gwt.

I've enjoyed using yui in the few small javascript modules I've written (tracked in google code), so one of my first typescript tasks was to publish typescript code as a yui module, and to use other yui modules from typescript. I'm new to typescript, so the following explanation may be wrong, but here it goes.

Typescript supports modules via module, export, and import keywords. A typescript module compiles to either an AMD or CommonJS style javascript module depending on a compiler flag (the typescript specification covers all this). So a typescript file like this:


/// <reference path="yui" />
/// <reference path="toyA" />


export module littleware.toy.b {
    
    export import modA = module( "toyA" );

    export class Greeter {
        delegate:modA.littleware.toy.a.Greeter;
    
        constructor(message: string) {
            this.delegate = new modA.littleware.toy.a.Greeter( message );
        }
        greet() {
            return this.delegate.greet();
        }
    }
    
    export function runGreeter( greeter:Greeter ) {
        var button = document.createElement('button');
        button.innerText = "Say Hello";
        button.onclick = function() {
            alert(greeter.greet());
        }
        
        document.body.appendChild(button);
    }

}

Compiles as commonjs like this:


(function (littleware) {
    (function (toy) {
        (function (b) {
            var modA = require("./toyA")
            var Greeter = (function () {
                function Greeter(message) {
                    this.delegate = new modA.littleware.toy.a.Greeter(message);
                }
                Greeter.prototype.greet = function () {
                    return this.delegate.greet();
                };
                return Greeter;
            })();
            b.Greeter = Greeter;            
            function runGreeter(greeter) {
                var button = document.createElement('button');
                button.innerText = "Say Hello";
                button.onclick = function () {
                    alert(greeter.greet());
                };
                document.body.appendChild(button);
            }
            b.runGreeter = runGreeter;
        })(toy.b || (toy.b = {}));
        var b = toy.b;
    })(littleware.toy || (littleware.toy = {}));
    var toy = littleware.toy;
})(exports.littleware || (exports.littleware = {}));
var littleware = exports.littleware;

This is the amd output for the same code:

define(["require", "exports", "toyA"], function(require, exports, __modA__) {
    (function (littleware) {
        (function (toy) {
            (function (b) {
                var modA = __modA__;

                var Greeter = (function () {
                    function Greeter(message) {
                        this.delegate = new modA.littleware.toy.a.Greeter(message);
                    }
                    Greeter.prototype.greet = function () {
                        return this.delegate.greet();
                    };
                    return Greeter;
                })();
                b.Greeter = Greeter;                
                function runGreeter(greeter) {
                    var button = document.createElement('button');
                    button.innerText = "Say Hello";
                    button.onclick = function () {
                        alert(greeter.greet());
                    };
                    document.body.appendChild(button);
                }
                b.runGreeter = runGreeter;
            })(toy.b || (toy.b = {}));
            var b = toy.b;
        })(littleware.toy || (littleware.toy = {}));
        var toy = littleware.toy;
    })(exports.littleware || (exports.littleware = {}));
    var littleware = exports.littleware;
})

The yui module system expects a module to register itself via a call to YUI.add with a closure function that accepts a YUI instance variable "Y" to use as the root of the module namespace. A YUI module for our typescript code could be implemented using the amd definition something like this:


YUI.add('littleware-littleUtil', function(Y) {
    // call the lambda passed as 2nd argument to amd define
    lambda( Y, Y, Y );
}, '0.1.1', { 'requires' : [ 'littleware-toy-a' ] } );

I was able to hack something to incorporate the amd module-definitions output from the typescript compiler into a YUI module system - there are just a few tricks.

The first trick is to introduce our own global define method that connects the amd module definitions with the YUI module system:


function define( argNames, moduleThunk ) {
  var name = null;
  // hacky way to get the YUI module name ...
  try { moduleThunk( null, null ); } catch ( v ) { name = v; }
  YUI.add(name, function(Y) {
    var thunkArgs = [];
    for( var i=0; i < argNames.length; ++i ) {
      thunkArgs.push( Y );
    }
    moduleThunk.apply( Y, thunkArgs );
  }, '0.1.1' );

Second trick - the YUI.add call that registers a module's closure with YUI requires a module name. The hack I came up with is to call into the amd module-definition with null arguments, and add a block of code to the typescript that checks for nulls, and throws a "module name" exception:


declare var exports:Y;

//declare module littleware.toy.a;
if ( null == exports ) {
    // Hook to communicate out to YUI module system a YUI module-name for this typescript file
    throw "littleware-toy-toyB";
}

var Y:Y = exports;

This is a complete hack that exposes the javascript compiler output to the typescript code, but it works. The
var Y:Y = exports;
exposes the YUI instance "Y" to the typescript code. Juan Dopazo posted his node script that generates typescript type-definitions for YUI. I saved the output file he posted as "yui.d.ts", cleaned it up a bit, and included that in my build, so the type-script compiler can perform type-checking on YUI calls. I modified the typescript toy to take advantage of YUI DOM utilities just to verify all this module magic worked:

  var counter = 0;

  export function runGreeter( greeter:Greeter ) {
      var toyNode = Y.one( "div.toy" );
      var messageNode = toyNode.one( "p" );
      var button = document.createElement('button');
      button.innerText = "Say Hello";
      button.onclick = function() {
          messageNode.setHTML( "" + counter + ": " + greeter.greet()  );
          counter += 1;
      }

      toyNode.append(button);
  }

The "YUI.add" module registration includes options for specifying a module's dependencies on other YUI modules, but I prefer to specify that information in the YUI-load configuration that tells YUI which javascript file contains which module. I include that code along with my global "define" amd-hack function in a little bootstrap.js file that I include in the html host file via a <script> tag.

/*
 * Copyright 2011 catdogboy at yahoo.com
 *
 * The contents of this file are subject to the terms of the
 * Lesser GNU General Public License (LGPL) Version 2.1.
 * http://www.gnu.org/licenses/lgpl-2.1.html.
 */

if( window.littleware == undefined ) {
    window.littleware = {};
}

/**
 * littleYUI module, see http://yuiblog.com/blog/2007/06/12/module-pattern/
 * YUI doc comments: http://developer.yahoo.com/yui/yuidoc/
 * YUI extension mechanism: http://developer.yahoo.com/yui/3/yui/#yuiadd
 * Provides convenience method for loading YUI with the littleware extension modules,
 * so client javascript code just invokes:
 *      littleware.littleYUI.bootstrap()... 
 *
 * @module littleware.littleYUI
 * @namespace auburn.library
 */
littleware.littleYUI = (function() {
    
    /**
     * Get the YUI.config groups entry that registers the littleware javascript
     * modules with - YUI( { ..., groups: { littleware: getLittleModules(), ... } )
     * @method getLittleModules
     * @return dictionary ready to add to YUI config's groups dictionary
     */
    var getLittleModules = function() {
        return {
            combine: false,
            base: '/btrack/resources/js/littleware/',
            modules:  { 
                'littleware-littleUtil': {
                    path: "littleUtil.js",
                    requires: [ "array-extras" ]
                },
                'littleware-littleId': {
                    path: "littleId.js",
                    requires: ['anim', 'base', 'node-base', 'node']
                },
                'littleware-littleTree': {
                    path: "littleTree.js",
                    requires: ['anim', 'base', 'node', 'node-base', 'test']
                },
                'littleware-littleMessage': {
                    path: "littleMessage.js",
                    requires: [ 'io-base', 'node', 'node-base', 
                           'littleware-littleUtil', 'test']
                },
                'littleware-feedback-model': {
                    path: "feedback/littleFeedback.js",
                    requires: [ 'node', 'base', 'littleware-littleUtil', 'test']
                },
                'littleware-feedback-view': {
                    path: "feedback/FbWidget.js",
                    requires: [ 'node', 'base', 'littleware-littleUtil', 
                       'littleware-feedback-model', 'test']
                },
                'littleware-toy-toyA': {
                    path: "toy/toyA.js",
                    requires: [ 'node', 'base', 'littleware-littleUtil', 'test']
                },
                'littleware-toy-toyB': {
                    path: "toy/toyB.js",
                    requires: [ 'littleware-toy-toyA']
                }                                                
            }
        }    ;
    };

    
    /**
     * littleYUI - wrapper around YUI3 YUI() method that
     * registers local littleware modules.
     */
    var bootstrap = function () {
        return YUI({
            //lang: 'ko-KR,en-GB,zh-Hant-TW', // languages in order of preference
            //base: '../../build/', // the base path to the YUI install.  Usually not needed because the default is the same base path as the yui.js include file
            //charset: 'utf-8', // specify a charset for inserted nodes, default is utf-8
            //loadOptional: true, // automatically load optional dependencies, default false
            //combine: true, // use the Yahoo! CDN combo service for YUI resources, default is true unless 'base' has been changed
            filter: 'raw', // apply a filter to load the raw or debug version of YUI files
            timeout: 10000, // specify the amount of time to wait for a node to finish loading before aborting
            insertBefore: 'yuiInsertBeforeMe', // The insertion point for new nodes

            // one or more groups of modules which share the same base path and
            // combo service specification.
            groups: {
                // Note, while this is a valid way to load YUI2, 3.1.0 has intrinsic
                // YUI 2 loading built in.  See the examples to learn how to use
                // this feature.
                littleware: getLittleModules()
            }
        });
    };
    return {
        bootstrap: bootstrap,
        getLittleModules: getLittleModules
    };
})();


/**
 * AMB module hook - still needs work ...
 * @param argNames {Array[String]}
 * @param moduleThunk {function(requires,exports,import1, import2, ...)}
 */
function define( argNames, moduleThunk ) {
  var name = null;
  // hacky way to get the YUI module name ...
  try { moduleThunk( null, null ); } catch ( v ) { name = v; }
  YUI.add(name, function(Y) {
    var thunkArgs = [];
    for( var i=0; i < argNames.length; ++i ) {
      thunkArgs.push( Y );
    }
    moduleThunk.apply( Y, thunkArgs );
  }, '0.1.1' );
}

Anyway - that's a typical javascript mess, but it lets me bootstrap a javascript "main" in a new page with code like this:

   littleware.littleYUI.bootstrap().use( 
                'node', 'node-base', 'event', 'test', 'scrollview',
                'littleware-toy-toyB',
                function (Y) {
                    var util = Y.littleware.littleUtil;
                    var log = new util.Logger( "events.html" );
                    
                    log.log( "main() running" );
                    var toy = Y.littleware.toy.b
                    var greeter = new toy.Greeter( "Dude" );
                    toy.runGreeter( greeter );
                }
        );

Hopefully that makes some sense. I pushed the code up to the littleware repo I've been committing to lately. That repo is a mess, but feel free to take a look.

Friday, May 17, 2013

Updating Web-login for Javascript Webapp

I've been coding away for several days on some old web-login logic I had implemented in littleware to work in web applications with JSF-managed UX. I'm updating the code for use in apps where a javascript program manages the user experience. I've been thinking lately about the similarities and differences between the two application architectures.

The first difference between the two designs is in deployment. The old JSF architecture relied on JSF and JSP templates managed by the server, so I would usually bundle up the entire application in a .war file, and deploy it to some glassfish or tomcat or whatever container. The user interacted with the application by clicking links and submitting forms that moved the browser between web pages rendered by the server.

I'm trying to structure the newer code so that most client-side assets (javascript, CSS, hadlebar templates, ...) are served as static files from S3. The user's in-browser interactions with the application trigger events that are handled by javascript event-handlers. The javascript code running in the user's browser can access remote services via cross-origin AJAX requests. There are various CORS servlet filters open sourced online that take care of setting the HTTP response headers that browsers look for; today I grabbed this one posted by some Ebay coders to github - hopefully it works.

In the login code, both the old and new setups rely on a request filter (javax.servlet.Filter) to intercept unauthenticated client requests. The old code would intercept an unauthenticated page-load request, and forward the request on the server to a login page via RequestDispatcher.forward.

The new code intercepts unauthenticated AJAX requests to JSON services, and responds to the javascript client with an HTTP 401 (unauthorized) response, and relies upon the javascript code on the client to initiate a login process that eventually authenticates with the server by submitting credentials to a login AJAX service.

Finally - in the older applications I had the bad habit of tracking session state on the server via beans stashed in container-managed in-memory session. Tracking user data in-memory on a particular server required that a client continued to interact with the same server it began a session with. In-memory session state also made it difficult to partition a server's functionality between different endpoints. In other words - if I had a server that implemented some functionality "ABC", and I later decided that I would like to split the functionality on that server (or server cluster) between separate "A", "B", and "C" servers (or clusters), then it would be hard to do that if the code relied on shared in-memory session state.

Anyway, the new code avoids session state on the server - instead it relies on the client-side javascript code to track session state in most cases, and transient cookies in a few others.

In the end - I get to throw away a bunch of crazy server-side JSF beans and templates, and replace them with javascript modules and REST services.

Saturday, May 04, 2013

scala REPL classpath hack

While writing code I often want to take a quick look at the behavior of some class or module, and might wind up writing a short test program just to verify that some method does what I expect or that I'm obeying some DSL's state machine or whatever. One of the great things about Scala (and groovy, javascript, clojure, ...) is its REPL, which allows me to test little blocks of code without the hassle of compiling a test file.

Unfortunately, Scala's REPL launch scripts (scala.bat, scala.sh) do not provide command-line options for manipulating the REPL's classpath, so the REPL can't see the jars IVY assembles for my project ( javasimon, joda-time, guava, gson, guice, ... ).

Anyway - it's easy to just copy %SCALA_HOME%/bin/scala.bat (or ${SCALA_HOME}/scala if not on Windows - whatever), and modify it, so the REPL runs with the same classpath as your project, and at the same time set the heap size, logging config-file system property, and whatever else is needed. For example, here's the shell.bat launch-script from a project I was playing with recently.

@echo off

if not defined JAVACMD set JAVACMD=java.exe
if defined JAVA_HOME set JAVACMD="%JAVA_HOME%\bin\java.exe"

@rem echo "mojo:  .\runTestCase.bat 2>&1 | out-file output.txt utf8"


%JAVACMD% -Xmx1024m -Xms1024m 
   "-Djava.util.logging.config.file=%~dps0logging.properties"  
   -cp "%SCALA_HOME%\lib\*;%~dps0\lib\*;%~dps0\*;." 
   scala.tools.nsc.MainGenericRunner -usejavacp %*

The "mojo" line is a reminder to me that
bla 2>&1 | out-file output.txt utf8
is the Windows powersell equivalent of
bla > output.txt 2>&1
in bash shell - something like that. I'm terrible in bash, and worse in powershell, but I try to at least be able to send output to a file, grep, and run commands in a loop ... ugh!

Anyway - once the classpath is all set, then it's REPL playtime!

> .\cli\shell.bat
Welcome to Scala version 2.10.1 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_0
9).
Type in expressions to have them evaluated.
Type :help for more information.

scala> import org.joda.{time => jtime}
import org.joda.{time=>jtime}
                                                    ^

scala> val t = jtime.DateTime.parse( jtime.DateTime.now().toString() )
t: org.joda.time.DateTime = 2013-05-03T16:34:48.496-05:00

scala> import com.google.common.{io => gio}
import com.google.common.{io=>gio}


scala> val UTF8 = java.nio.charset.Charset.forName( "UTF-8" )
UTF8: java.nio.charset.Charset = UTF-8

scala> gio.Files.write( jtime.DateTime.now().toString(), 
         new java.io.File( "bla.txt" ), UTF8 )

scala> val t = jtime.DateTime.parse( 
      gio.Files.toString( new java.io.File( "bla.txt" ), UTF8 ) 
    )
t: org.joda.time.DateTime = 2013-05-03T16:37:35.561-05:00

scala>