Saturday, July 25, 2009

How to host Silverlight (.xap) on Google App Engine with Java SDK

...or any other file with a MIME-type that Google App Engine does not treat nice by default.

Problem: Lack of control over MIME-types and static files on Google App Engine

Apparently, it is not possible to host a .xap file as a static file on Google App and register a correct MIME-type for it. If you search around, you might find hints that it is possible to do with the Python SDK (configuring handlers), but you might also find people can't get the MIME-settings to work with the Java SDK. Recently, I was one of the later, so here is a solution for you that hopefully will save you some time.

Solution: Create a servlet that loads the .xap file as a resource and streams it to the client
This part might sound complex but really is simple. Here are the steps to get it working, though you might need to refine it for production:

1) Produce your .xap file, test .html file and silverlight.js file and copy those into your war folder. Here is my test example structure in an Eclipse project:

2) Create a HttpServlet-extending Java class file (that I named NaiveFileServlet.java) with content similar to the following:



3) Register .xap files as a servlet resource in appengine-web.xml:


4) Register your servlet and URL-patterns in file web.xml:


5) Deploy your app as you normally do, visit the test .html page and enjoy your Silverlight app.

Here is a running example: http://yoaws-slogaet.appspot.com/ (click and move your mouse).


Saturday, July 11, 2009

OnTime for Scrum? Step#1 - Customization

The Scrum Master and the Product Owner customizes.
A simulation of a Scrum team using OnTime...

Background
Per Owen once asked himself: "Is that OnTime software really any good for doing Scrum?".
To figure out an answer to this question, he went to management and got himself 1) a new project to work on, and 2) a role as the project's Product Owner.

Management is wise, so they also assigned this evaluation project their newly educated Scrum Master, Sara Mart, and 2 Team Members: Tim Mee & Tom Bert. In this way they would get to evaluate OnTime as a tool to be used within a project using the Scrum framework.

The Scrum Master customizing OnTime
Sara Mart eagerly downloaded OnTime 2009 from http://www.axosoft.com/.
Apart from the usual SQL Server configuration querks, she soon had the OnTime Windows client application starting up. Sara usually felt more productive with an OS native application, though she acknowledged that the OnTime web application could come in handy at some point in time... for some.

Defects, Features, Tasks and Incidents?
The first puzzle to solve for Sara was to get the Scrum terminology into OnTime. Her first impression of OnTime was that it focuses on management of 4 primary data list: Defects, Features, Tasks and Incidents. Fortunately, the names of these list can be customized, so she changed them to: Product Bugs, Product Backlog, Sprint Backlog and Impediment List.


Although the Product Bugs might not be a Scrum artifact, Sara thought it would be nice, if a bug could be pulled into a sprint just like a user story can be pulled from the Product Backlog.

Project Wiki and Roles?
Sara also embraced the Project Wiki page, since this could show to be a nice communcation mean for the team. She created a project page listing the project members, which reminded her of creating them as OnTime users. This task was simple to do and to her surprise OnTime has Scrum roles that can be associated with a user.

Thats it, Sara thought, and she went to see Per Owen, so they could try populating the Product Backlog together.

The Scrum Master and Product Owner customizing the Product Backlog
Per Owen had just finished installing OnTime when a very positive Sara entered his office. He was soon logged in and updated about the changes Sara had made.
They had just begun looking at the data list now named Product Backlog, when Per heard the words: "Oh no, this ain't going to work".

The default Product Backlog view needs nursing
Unfortunately, Per was the owner of this statement, so he now owned Sara (and himself) an explanation. Per explained to Sara (and himself) that the default setup of the Product Backlog was not really what he wanted. A little hour later this minor setback was turned into a positive experience for both Sara and Per.


Per user changes
As the Product Owner and a new OnTime user, Per didn't want too much information to begin with, so Sara helped him disabling all other views but the Project Wiki and the Product Backlog.
Furthermore, Per would like a little more clean Product Backlog view, so they disabled the Assigned To column, enabled the Original Estimate column, and made the following system wide changes.

Per system changes
In OnTime all data fields are associated with a field label that an administer can change, so Sara logged in and changed 'Feature Id' to 'Story Id'.

Per needed to be able to value each story in terms of business value, that is, how much worth a released story would become. OnTime didn't really have a column that could be used to represent this. Priority couldn't really be it, since more complex things like dependencies, resources and external opinions affects priority.
After some searching around, Sara and Per settled on creating a new system wide custom field; an integer called 'Business Value'.

Product Stories Workflow Template
The workflow column in the Product Backlog is an optional state management tool that Sara and Per agreed on trying out. Obviously, the default workflow template didn't match Per's needs, so they decided to make a new template one.
Per would like everyone to add new stories to the Product Backlog, so they created a 1st step name New and configured OnTime such that all could create a new story and it would be marked as New by default.
2nd step they called Valued meaning that the Product Owner, Per, would value the new story. 3rd step they called Estimated and made the team (Developer role) responsible for getting a story into this state. 4th step they called Prioritized, since that would be Per and Sara weighting business value, estimates and what not for each story, and assigning a priority. 5th step they called In Production meaning commited to a sprint by the team and Sara.
A 6th step would be one of the the possible outcomes for a story in production: Released (in working software at end of sprint), Descoped (not released at end of sprint) and Aborted (not released since sprint was aborted).
In OnTime each state can associated with a next allowed state, so Sara and Per specified state progresion for stories as a simple state graf 1->2->3->4->5->(6|7->2|8->2) with an outer loop for Descoped and Aborted.

Wednesday, June 3, 2009

Feel the bliss of the design pattern InstanceRegistry

The InstanceRegistry pattern values loose coupling between objects. This pattern is as simple as the Singleton pattern, but with the InstanceRegistry pattern your objects stay simple, replaceable and testable - even you manager objects.


Your choice: Tightly or Loosely?

"Until somone changes my mind, I will always use Pete Bong for plumbing, Tira Donk for carpentry and Rolli Streak for decorations." - Foo

Above statement from object Foo raises the following dependency concerns:  
  • Foo's abilities cannot be tested without Pete Bong, Tira Donk and Rolli Streak,
  • Foo's abilities cannot be used without Pete Bong, Tira Donk and Rolli Streak, and
  • Foo needs to changed, if Pete Bong, Tira Donk or Rolli Streak needs to be replaced.

"Whenever I need handywork done, I just lookup an available plumber, carpenter or decorator."  - Bar

In constrast to Foo, above statement tells us that Bar has the following dependency strong points:
  • Bar's abilities can be tested with any plumber, carpenter and decorator,
  • Bar's abilities can be used with any plumber, carpenter and decorator, and
  • Bar is satisfied to use an externally defined plumber, carpenter and decorator.

Now, should you at this point be in doubt which object to prefer - Foo or Bar - then I fear that the rest of this entry does not have more to offer. On the other hand, if you now are thinking in the lines of 'I like a Bar, but how expensive is it?' then hang on for the bliss...

Your Battle: Foo vs Bar

Imagine Foo would have code that looked something like this:
PeteBong plumber = (PeteBong) PeteBong.getInstance();
plumber.buildSomething();
This kind of code is pretty common, causes the previously mentioned concerns, but also has the very nice feature that the reference to PeteBong is fetched when needed. Last mentioned feature is possible, since PeteBong is globally available as a static reference via the Singleton pattern. 

Now a Bar version of this code uses the InstanceRegistry pattern:
IPlumber plumber = (IPlumber)InstanceRegistry.getInstance('IPlumber');
plumber.buildSomething();
or even better
IPlumber plumber = instanceRegistry.getInstance<IPlumber>();
plumber.buildSomething();
Here Bar is tightly coupled to an InstanceRegistry that is basically just a map between ids and object instances. Whether this id is a string or a type is up to you, but in the later version you have the ability ensure loosely coupled objects by only accepting interfaces as ids. Please note that the getInstance method simply looks up a reference to an object that has registered itself in the InstanceRegistry and, thus, become globally available to other objects. The InstanceRegistry does NOT create new instances.

Since Bar is using the InstanceRegistry pattern it has the following properties:
  • Bar can be tested with mock up implementations of its dependent interfaces e.g. IPlumber,
  • Bar can be used with any implementation of its dependent interfaces e.g. IPlumber, and
  • Bar is designed work with objects that may change implementation, but not specification. 
Your Exercise: An InstanceRegistry implementation

Here are some considerations to do when creating an InstanceRegistry implementation. I hope the missing implementation details will become some nice discussion subjects, and that you will have fun making this pattern yours.
  • Decide whether to make an InstanceRegistry interface or not, and imagine how it would be used,
  • Decide how to pass your InstanceRegistry implementation reference around,
  • Decide on methods and arguments for adding and removing the object instances that can be be fetched via the getInstance method, and
  • Decide on other useful methods that the InstanceRegistry might have.
Enjoy the bliss, give feedback and start discussions.

Thanks!

Wednesday, May 13, 2009

When you can't afford to use Subversion

A team doing iterative development, and having project data above or around ½ GB, should invest in a fast Configuration Management System.


Let me clarify why:

- iterative development means frequent branching, and frequent branching means frequent download of all data from a branch => fast download is required,

- frequent branching means frequent synchronization between branches => fast and good difference queries are required, and

- a team with a handful or more people updating and committing means many changes => fast update and commit cycles are required.


Why pick on Subversion?

Don't get me wrong, I like Subversion. I think it is doing tremendous benefit worldwide everyday, but some of it strengths are also its limits.

You can work off line with your Subversion checkout, which is cool when traveling around with a laptop. I do so, and I think the ability to add/delete/revert offline is brilliant.

However, this is only possible because of the .svn folders that are created on your hard drive (when doing a checkout) and the algorithms in your subversion client.

In this design decision resides a clever approach - but alas - also a scaling problem.


What Subversion scaling problems?

- .svn folders are created per data folder => each data folder needs to be traversed by the Subversion client algorithm (on the client computer) and synchronized with a server,

- each .svn folder contains a .svn/text-base folder with a server copy of all files in your data folder => the Subversion client copies server data to the client computer, and syncs against this,

This is essential delegation of CMS server work to a client pc, which is clever, but comes at a price. The price is data duplication and added processing time.


Yeah, but with todays PC's?

In 3 years I worked with project data ranging from ½ GB to 2 GB using Perforce; a costly - but fast - CMS that did its job.

The first year a management interest in changing to Subversion blossomed, and a project with a couple of GB data was added to the Subversion server, which resulted in nagging team members. They were used to something faster.

A year after another management interest in changing to Subversion came around, and a group was to investigate the performance of Subversion vs. Perforce. The group could verify that it was a good idea for some projects - those with a lot of data - to use Perforce.

Recently, I worked with another team that had around 4 GB project data when checked out from Subversion. This team had new machines, but it could take 15 min. just to update a project branch.


Symptoms you might avoid by paying for a fast CMS

- you might avoid that people don't want to update often, because the CMS is too slow,

- you might avoid that people don't want to branch, since checking the new branch out is too painful,

- you might limit how often people are interrupted while working while waiting for SCM operations to complete, and

- you might avoid that your continuous integration servers are slow with responses.

No Guarantees? No. Unfortunately not. The elimination of a CMS speed problem does not rid one from all other CMS related problems.


Tips when stuck with a slow CMS

- Think that bad SCM decisions/practices are expensive,

- Keep original third party in its own repository,

- Keep modified third party in its own repository,

- Divide your project data into repositories e.g. products or even components.


Thanks for reading this far. I hope you found some of it useful.

(Please send a comment. Feedback is greatly appreciated.)