Saturday, November 24, 2012

National Dog Show

The National Dog Show was on NBC last night, and was a lot of fun to watch if you're a dog lover like me. It's great to see people with their pets in positive relationships, and having fun together.

Of course it's much better to adopt from a shelter or breed-rescue organization than to pay a breeder or (much worse) pet store for a dog or cat. So many beautiful animals are killed every year for want of a home - it doesn't make sense to pay money to add to the pet population rather than adopt an animal that needs a home. Many shelter dogs are purebreds or close relatives too. Anyway, the Humane Society has a great little article: "The Top 5 Reasons to Adopt".

Saturday, November 17, 2012

R.I.P. Twinkie

The NYTimes had an article the other day reporting the planned liquidation of Hostess under Chapter 7 bankruptcy. Management decided to throw in the towel blaming a a failure to negotiate a contract with one of its workers' unions.

Unfortunately the article did not cover Hostess' history of mismanagement including private equity backed mergers and debt loading (this Forbes article has more detail); so the article's comment stream collected many posts bashing the union.

I know nothing about Hostess or its history, but ignorance has never stopped me from offering an opinion - I'd never say anything otherwise. Here's a copy of the comment I posted to the article:

It looks like Hostess failed, because it failed to develop compelling products. Twinkies and Wonder were once trail-blazing brands. A popular snack can demand large markups, but today people don't want to eat twinkies at any price. Management deserves blame for failing to adapt to a changing market.

Many older companies (Sony, H.P., ...) suffer similar problems in their markets. The company has outlived its visionary founders, and is left to stock holders and M.B.A.s who see the company as a collection of assets to manage for optimal profit rather than a vehicle for realizing the founders' dreams.

Saturday, November 10, 2012

Running Windows 8

A couple weekends ago I took advantage of Microsoft's $40- Windows 8 offer, and have a spanking new operating system running on my workhorse Dell 1557 laptop.

Running W8 is like having a new machine! It's always fun to see what these monster software companies (Microsoft, Google, Apple) can crank out.

The OS does suffer from multiple-personality disorder. The "RT" personality for new full-screen apps is well suited for a touch-tablet user or a user that spends all her time in a single-window application - reading a web page or whatever.

Fortunately - W8 also still has its old "desktop" personality - which is where I spend most of my time when coding - switching between multiple open windows (IDE's, browsers, shells, control panel, ...).

For either environment - if you install Windows 8 on a standard (non-table or non-touch) laptop, then you'll want to become familiar with the new WinKey+ keyboard shortcuts. I was much more comfortable and productive with W8 once I became comfortable with the WinKey+Tab,C,L,R,X,Z shortcuts.

So W8 is a little bit of a Frankenstein with pieces of different creatures stitched together into a monster, but I like it. It's new, looks great, and is a brave first step in a new direction by Microsoft.

Saturday, August 25, 2012

scala companion package

I wrote a scala trait the other day with a "companion package" instead of the usual "companion object". I was pretty happy with how the code came together, so thought I'd write a quick post to my poor neglected bLog.

I often write a scala trait that defines an interface to some tool that manages access to a data repository or manipulates data in some way. I usually define the interface traits to different tools provided by some module "bla" in a "bla.controller" sub-package. I define bla's data model in a "model" sub-package, and classes that simply support a tool's interface in the tool's companion object, so something like this:

package bla
package controller

trait Tool {
    def get( id:String ):model.Data
    def search( query:String ):Tool.SearchResult
    ...
}

object Tool {
    case class SearchResult( query:String, matches:Iterable[model.IndexEntry] ) {}

    object SomeEnum extends Enumeration {
       val A, B, C = Value
    }

    trait Builder {
       var creds:Credentials = null
       def creds( value:Credentials ):this.type = {creds = value; this }
       
       var endPoint:URL = new URL( "http://default.end.point" )
       def endPoint( value:URL ):this.type = { endPoint = value; this }

       ...
       def build():Tool
    }

    /** Factory necessary if not running in IOC container - ugh */
    object Factory extends Supplier[Builder] {
        def get():Builder = internal.SimpleTool.Factory.get()
    }
}

Anyway - that pattern works great most of the time, but the other day I was working on a tool with several supporting types in the companion object, and the Tool.scala file was growing fatter than I like. Fortunately - it turns out we can accomplish the same semantics as a companion object with a companion package like this:

package bla
package controller

trait Tool { ... }

package Tool {
    // ...
    object Factory extends Supplier[Builder] { ... }
}

The companion package approach has the advantage that we can split out some of the types defined in the companion package to their own files, so we could have a bla/DataHelper/Factory.scala like this:

package bla
package controller
package Tool

object Factory extends Supplier[Tool] { ... }

The companion package can define "static" constants in a package object, and we can move the tool-specific implementation classes to its own bla.controller.Tool.internal package rather than the shared bla.controller.internal package.

Finally - changing companion object code to the companion package pattern does not require changes to client code (code that uses Tool) - just a recompile.

Anyway - I like the way things fit together with the companion package pattern.

Wednesday, May 09, 2012

Extra S3 log parameters with AWS Java SDK

Amazon web services' S3 REST API supports custom access log information by adding custom query string parameters beginning with "x-" that S3 ignores but logs. Unfortunately custom query parameters are not directly supported in the AWS Java SDK, so we were planning to drop down to writing HTTP REST code for a recent project that required logging of some custom client-session parameters.

I hate working with HTTP, so I was glad when we figured out a workaround. The trick we came up with was to register a custom RequestHandler with our instance of the SDK's AmazonS3Client. The RequestHandler is an internal class in the API, so it's not included in the API documentation, but you can download the source code to see its simple interface:

/**
 * Interface for addition request handling in clients. A request handler is
 * executed on a request object before it is sent to the client runtime
 * to be executed.
 */
public interface RequestHandler {

    /**
     * Runs any additional processing logic on the specified request (before it
     * is executed by the client runtime).
     *
     * @param request
     *            The low level request being processed.
     */
    public void beforeRequest(Request request);

 /**
  * Runs any additional processing logic on the specified request (after is
  * has been executed by the client runtime).
  *
  * @param request
  *            The low level request being processed.
  * @param response
  *            The response generated from the specified request.
  * @param timingInfo
  *            Timing information on the request's processing.
  */
    public void afterResponse(Request request, Object response, TimingInfo timingInfo);

 /**
  * Runs any additional processing logic on a request after it has failed.
  *
  * @param request
  *            The request that generated an error.
  * @param e
  *            The error that resulted from executing the request.
  */
    public void afterError(Request request, Exception e);

}

So the RequestHandler's beforeRequest method can add parameters to a Request before it is processed by the underlying HTTP engine. The only trick is to determine which parameters to add to a particular Request, but it's easy to extend the SDK's API-level request objects (like S3's GetObjectRequest) with subtypes that add application-specific properties, then check for for those subtypes in the RequestHandler via the getOriginalRequest accessor.

Oracle Google Comments

For some reason I was inspired today to post a comment on the NYTimes Bits bLog's post on the Oracle-Google lawsuit. I thought I didn't make it through the Time's idiot filter, but they actually put my comment online. Crazy. Here it is again:


I think Google got itself into trouble, because rather than simply build on top of java (write code with the java language and libraries), and contribute to the java community; Google decided to "fork" java to make its own language that is nearly identical to java, but with various differences (security model, libraries, bytecode) at a time (pre-openJDK) that java was not open sourced. Often non-UI code (networking, database, ...) written in java can be easily recompiled for Android's "Dalvik" runtime, so Google gained instant access to the java developer community and programming tools; but the two systems are not the same.

There's something slimy about what Google did - forking java for Android without respecting the time and money Sun invested. Sun Micro sued Microsoft years ago when Microsoft released a version of java with incompatibilities to improve java on windows. Google was very careful to never call Android's runtime "java" to avoid the issues Microsoft ran into, but everybody thinks of Android as running java. Google should have just bought Sun Micro when it had the chance ...

Oracle is slimy too for trying to insinuate itself into the Android smart phone and tablet market. Oracle and Sun didn't have the vision of Apple, or the skill to imitate Apple quickly like Google; so now Oracle is trying to sue its way into the market.

Anyway - the best outcome when two corporate monsters fight is that they both get cut up and bleed ... ;-)

Friday, April 13, 2012

Steve Jobs - what a jerk!

I read Isaacson's Steve Jobs biography a couple months ago, and really enjoyed the read. One thing that surprised me - although I guess it's well known - was what an asshole Jobs was. He was just a really mean and selfish guy a lot of the time.

Of course Jobs was an amazing success on many levels, so everyone forgives him for being a jerk, and many argue that his acrimony contributed to his triumphs. On the other hand, many people also espouse the "No Asshole Rule" of management - which also makes sense, but it's ironic that a typical supported of the no asshole rule is an asshole.

Anyway - I think it's healthy to have at least one asshole; otherwise you wind up full of shit.

Tuesday, January 31, 2012

iptables NAT port forward 443 (https) to 8443

I recently wanted to setup port forwarding on an Ubuntu Linux server (AWS EC2) to redirect https traffic (port 443) to a Tomcat server listening for SSL connections on port 8443. I really did not want to learn anything about UFW or iptables - I just wanted to setup the forwarding and get on with my day, so I proceeded to Google away and read man pages and finally figured out the following commands after learning more than I wanted to learn - which was a complete waste, because I'll forget it all anyway:

sudo iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-ports 8443

sudo iptables -t nat -A OUTPUT -p tcp --dport 443 -o lo -j REDIRECT --to-port 8443

The first command adds (-A) a rule to iptable's PREROUTING table to redirect incoming packets bound for port 443 over to port 8443. The second rule adds a similar rule to the OUTPUT table that redirects packets outgoing to port 443 on the loopback interface (-o lo).

Of course there's another trick - those rules disappear on reboot unless we save them somewhere. If you're running UFW, then add the rules to /etc/ufw/before.rules. Otherwise one solution is to install the iptables-persistent extension (on Ubunutu: sudo apt-get install iptables-persistent), and save the rules to /etc/iptables/rules.v4.

I hate this sysadmin garbage ...

Wednesday, January 25, 2012

Simple Session Scope with Guice

I've been a big fan of the Guice dependency injection library for a while, but I missed support for session-scoped injection until I figured out a way to achieve the same effect using child injectors. I was inspired by the PicoContainer project that I stumbled upon several months ago. I haven't actually used PicoContainer, but it appears to actually be better thought out than Guice - implementing arbitrary dependency injection scopes and lifecycle management via hierarchies of IOC containers.

I had PicoContainer's hierarchy approach bouncing around in my head when I stumbled up Guice's createChildInjector method - which supports a similar approach to managing object scopes.

Long story short - I introduced the notion of a "SessionModule" that defines session-scoped bindings to littleware's module system in my development repository clone. Littleware's module system also uses OSGi in an unorthodox way to manage the application life cycle. I wish I would have known about PicoContainer earlier - it appears to implement a nice approach for a combined IOC and application life cycle container. At some point I need to take a look at Spring too - to steal ideas if nothing else!

Sunday, January 08, 2012

Youtube to the rescue!

I have this old yellow Kitchenaid blender that has been sitting in the cabinet collecting dust for the past year or so after the rubber coupler that mates the motor base with the pitcher's blade impeller melted when I left hot soup in the pitcher for too long. It was so frustrating to have this appliance with working motor useless from a melted piece of rubber - what a piece of garbage! I tried some ridiculous jerry rigs, tried to remove the part, googled "busted blender", and eventually just stuck the thing in a cabinet disgusted.

Anyway, happy ending, yesterday I was thinking again about the damn blender after watching America's Test Kitchen make some awesome gazpacho - trying to figure out how I could puree without a food processor or blender, when I decided to google "kitchenaid blender coupler" - something like that, and discovered a community of pissed off blender owners and their relief at discovering how to repair the busted rubber coupling! This YouTube video shows how to remove the part, and Amazon sells a replacement.

I'm waiting for my new coupler to arrive in the mail. I can't wait to give the repaired blender a try. It's like I'm getting a new blender for Christmas! I'll probably wind up blending my hand off or something like that now ... blood smoothie!