Sunday, February 23, 2014

Is HTML 5 over-hyped?

For over 10 years I have been watching the efforts of many smart people to “fix” HTML and come up with a new version of this most successful information encoding format. Over this time my attitude has been evolving through:
  • Naïve enthusiasm – HTML4 sucks and we are going to fix it!
  • Feeling daunted by the scope of the undertaking.
  • Frustration by the lack of progress on XHTML 2.0 – it’s all just talk, talk, talk and ever-increasing complexity.
  • Questioning the assumptions, benefits and motivations for the change – is HTML 4 really broken, or just mildly annoying? Is it more annoying than many other things we live with just fine? Yes, WHATWG largely captured the frustration, but are they suggesting anything better?
  • Indifference. I could use HTML4, or 5 or 55 – it is the information and presentation that matter, not how you encode it.

Over the last month I have been implementing a proof of concept solution using modern web-application stack, and I had to catch up with the current state of HTML, CSS and JavaScript. Let’s say that of all three, I find HTML5 to stand out in a weird way – there is a lot of noise in the Web, yet there is nothing so special about it…

In fact, it looks like HTML 5 and its cute logos have turned into an umbrella term for a set of initiatives, of which the actual evolution of the HTML markup language is one of the least interesting aspects.

So, what does HTML 5 bring over the “legacy” HTML 4 / XHTML 1.1 – let's see:

A bunch of new browser APIs and formal specification for many existing ones. This is the most significant achievement of the WHATWG/W3C work, though I am not very clear why is it billed as part of HTML 5. Even if I use a HTML 4, I can still take advantage of these APIs on the JavaScript side.

Standardization and specification of layout rules and processing models. Get rid of the SGML grammar. Again a very significant improvement, and again not related to the changes in HTML The Language.

Improved semantics with new elements like
, and Too little, too late. The world has moved on and the preferred way of expressing semantics is with classes. Clashes also work well with the current crop of JavaScript tools and CSS. Adding the new semantic elements is
codifying small part of all possible semantics in somewhat arbitrary ways (i.e. we’ve got “nav”, but what if we need to semantically distinguish between primary and secondary navigation? How is
anything more than a thin layer of syntax sugar over
or
?)


I've heard people talk how semantic markup is important for "serious publications". The fact is that HTML was never a first choice for serious publications, documents are typically mastered in specialized formats like LaTex, DocBook, FrameMaker, DITA , which are compiled to whatever version of HTML and the new semantic elements only force them to change the mappings in their compile scripts.

The bottom line is that while I will gladly make use of the new elements and I do find them nice, the impact that they will have on my output cannot be compared with the impact of CSS3, D3.js or underscore.js (which get much less news exposure).

Native multimedia support with tags like Again, a lot of noise about marginal improvements. We’ve been able to put media on the web since early 2000s – yes, it was relying on non-standard plugins, but that obviously didn’t stop YouTube from becoming multi-billion business. Nice, needed, but not really innovative or game-changing.

Embedding of SVG and MathML. That is nice – one problem I see that both SVG and MathML are monsters of specifications (good that they didn’t throw XForms into the mix) and we would never get to the point where they would be fully supported by all major browsers. On the positive side, the situation is better than during the Browser Wars, as the specs are already published, and we are not trying to standardize as we go. On a more pedantic point, while the embedding functionality is a feature of HTML, it is hardly innovation - most of the actual work is done by the long time existing SVG and MathML specs, so to say it's a feature of HTML is a bit disingenuous.

So, to summarize – HTML5 brings us a lot of standardizing and specifying of what was already there (making them more robust and simpler, but not really game-changing). It is a major milestone for browser implementers, but for content developers it only brings minor improvements and a whole set of arbitrary changes. If we compare this with the improvements in CSS and the Cambrian explosion in the world of JavaScript in fact HTML5 looks fairly dull and pedestrian.

Monday, December 9, 2013

Gamification

Humans love games – complex or simple, realistic or abstract, lonesome, competitive or cooperative – games are what we do when we are not forced to do other stuff, like you know… work?

Working is what we do in exchange for something we want, while games we enjoy for their own sake. The easiest way to turn a game into work is to introduce a high-stakes reward – something we desire more than the pure joy of playing. By shifting the motivation, we introduce performance stress which has far-reaching implications for the satisfaction of performing and the overall quality of outcome. In team games, high-stakes rewards complicate matters even further, as the reward needs to be distributed. This gives rise to politics and dissatisfaction and ultimately turns an egalitarian meritocracy into competitive hierarchy.

A logical approach would be to try it the other way around – remove the reward component from work and try to get people to do it for free, or as Carl Marx eloquently proclaimed:

In a higher phase of communist society, after the enslaving subordination of the individual to the division of labor, and therewith also the antithesis between mental and physical labor, has vanished; after labor has become not only a means of life but life's prime want; after the productive forces have also increased with the all-around development of the individual, and all the springs of co-operative wealth flow more abundantly—only then can the narrow horizon of bourgeois right be crossed in its entirety and society inscribe on its banners: From each according to his ability, to each according to his needs!


– Carl Marx, “Critique of the Gotha Program”

We all know what followed, and it was hardly a success. So, can we do better? Of course we can – here is another source of inspiration:
“Hello, old chap, you got to work, hey?”

Tom wheeled suddenly and said:

“Why, it’s you, Ben! I warn’t noticing.”

“Say – I’m going in a-swimming, I am. Don’t you wish you could? But of course you’d ruther work – wouldn’t you? Course you would!”

Tom contemplated the boy a bit, and said:

“What do you call work?”

“Why, ain’t that work?”

Tom resumed his whitewashing, and answered carelessly:

“Well, maybe it is, and maybe it ain’t. All I know, is, it suits Tom Sawyer.”

“Oh come, now, you don’t mean to let on that you like it?”

The brush continued to move.

“Like it? Well, I don’t see why I oughtn’t to like it. Does a boy get a chance to whitewash a fence every day?”

That put the thing in a new light. Ben stopped nibbling his apple. Tom swept his brush daintily back and forth – stepped back to note the effect – added a touch here and there – criticised the effect again – Ben watching every move and getting more and more interested, more and more absorbed. Presently he said:

“Say, Tom, let me whitewash a little.”

Now, that’s definitely better – at the end of this story – on top of having the fence painted by other boys, Tom gains an apple, a kite, a dead rat (along with a string to swing it with), twelve marbles, couple of tadpoles, six firecrackers and etcetera and etcetera. In other words, the dream of every gamification consultant.

So, I hear you say, all we need to do is spin the propaganda machine, pump the image of work and induce sense of purpose? Well, that has also been tried. The problem is that it is not sustainable and lacking the competitive dynamics and reward mechanism to distinguish the good from bad workers, the quality of the work is hit or miss.

As any Bulgarian railroad worker will tell you, the money spent on repairing all the sections built by volunteers in the 50s far exceed the money it would have taken to build them with paid labor.

The current trend is to use the latest neuropsychology research and try to structure work activity in ways that evoke gaming responses, without it being actually presented or recognized as game. This in fact appears to work… in a few showcase examples.

The problem is that in order to get the best results, the manipulation should be subtle, honest and carefully targeted, while most of the time what actually gets implemented ends up crude, shallow and generic.

Consider the following gamification clichés:



  • Let’s change the meaning of a bunch of words and do code-speak, expressing trivial thoughts through exotic metaphors.
  • Let’s count some stuff (like badges and points) and applaud the one that gets highest number.
  • Let’s do stuff at random and periodically check whether any of them has solved our problem.

While all of these may tickle our creativity, we can hardly call them an efficient way of solving a problem. Much too often, our brain finds a way to shortcut the uninteresting work and skip straight to the entertainment (i.e. gaming the metrics).

Here is some anecdotal account of our attempt to improve software quality by gamifying our continuous integration:

Few years ago, on a project far, far away, we used the Jenkins’s CI game – you know – the one where one gets points for not breaking the build, removing TODO items and adding tests (and loses points for the opposite).

While it was fun for a while, we also realized that the best way to get high score was to avoid doing things that may trigger a penalty – things like: taking initiative in cleaning up technical debt, improving the build-script, improving the testing framework code, adding new TODO comments to mark problems we can’t fix now, or removing useless tests.

Of course, all these things needed doing and being the responsible team we were, we did them, but then the very people that put the most effort in making the system better - they got the lowest score. After a while, we just stopped caring about the game.

There is another related trend worth mentioning – mixing work with entertainment, so the work becomes less boring (i.e. improving engagement). It is not a new trend – everybody does it to extent, but clearly there is a point when we tend to go overboard. In particular, I find that the propensity for seeking "fun" mirrors the Maslow hierarchy of needs – the higher the living standard, the more concerned people are with making their experience at work “fun”.

In corporate environment this is often manifested as managers, consultants and fat teams, devising process innovations which don’t bring empirical benefits, but comply with all the latest buzzwords and industry best practices, while the lowest level of support are barely scraping to hold the world from falling apart.

Many methodologies and management fads explicitly seek to appeal to the playful nature of our human brain and define complex models and processes, exaggerating the actual benefits of esoteric (but never too difficult) activities, maximizing personal satisfaction, but not necessarily the desired outcomes. Some even go a step further and institute metrics measuring the “fun stuff”, claiming that this is somehow a proxy metric for productivity.

So, where does that leave us? Here is a list of unsubstantiated assertions you may want to consider:


  • Gamification can help with engagement and commitment, but in order to get sustainable results, it needs well defined objectives and overall strategy. Also it needs to be supplemented with adequate, tangible rewards that actually matter to the participants (unless you are running a cult).
  • Setting a “fun” goal can do wonders to create commitment, but you either have to update the goal periodically, or tie it to something meaningful on a personal level in order to retain the effect in the long term.
  • Watching numbers go up is one of the easiest ways for creating engagement, but beware of unintended effects over time, as people rationalize the situation and start to game the metrics.
  • Gamification should be a part of a toolkit – its strength is in kick-starting behavioral change, but used on its own, it is unlikely to deliver tangible and long-lasting results.

...for some gamification means presenting work as game, for others - pretending game is work.

Wednesday, September 14, 2011

Common scenarios for Java application packaging

It all started from an overgrown answer to a question on StackOverflow. I realized that I haven't seen an overview of best practices and patterns for packaging of Java applications. There are the platform specific packaging formats, but they have more to deal with installation, rather than the layout of the packaged application. Below are a few common scenarios I've come across over the last few years.

Note: I've written another, somewhat related article on SO, about common strategies for managing configuration files in Java

A single uberjar with MAIN-CLASS specified in the manifest is convenient distribution format for simple tool applications that are intended to be run on the command line. You can copy it around and plop it somewhere on the path or in your home directory.  If you set the PATHEXT and file associations on Windows, you can run them as if they were native executables. One thing to watch out for is when you bundle libraries with custom entries in the manifest (you might need to manually merge them), when multiple jar's contain files with the same paths but different content (i.e. Spring namespace handlers, ServiceLoader implementations, LDAP SPI providers, etc.)

If for some reason you are bundling a library and all dependencies as a single jar (bad idea), you better take care to relocate the packages (for example, see how the JDK has relocated Xerces and BCEL under com.sun.org...) Not doing so can cause subtle problems to your clients which are extremely annoying, to say the least (*caugh*Weblogic*caugh*). On the other hand, relocating classes causes problem with smart usages of reflection relying on string concatenation. Also, you will most likely need to filter all XML and properties files, replacing the packages with the relocated names. All files under META-INF/services will need to be renamed too. All in all, bundling dependencies in a library jar causes far more problems than it solves.

When your application has more than a few options, you may find you want a config file. One approach I like is to package a template config in my app and look in a predefined location for override (i.e. in ~/.myapp) - you may provide instructions how to extract the template config and place it under the users home or you can have the app do it automatically on first usage. Which one you choose depends on your estimate how often an user will need to tweak the configs (we don't want to pollute the user home unnecessarily). A single directory app is usually installed in your user home directory.

If your application has dependencies on external services or special environment, you will need a startup script (shell or batch file) - in this case, the simplest deployment layout is single directory with uberjar and startup script. As you now have a directory, it is a good idea to add a README file and you may as well put the configs there. There are a number of variations on this theme. Usually, you want to add this directory to the app classpath as well, so any file there may be looked up as resource - that provides convenient way to override things like Spring descriptors, patch single classes, etc. These are usually installed in your home, /usr/local, or sometimes under opt.

If your application bundles many dependencies, has complex configuration, startup scripts for multiple platforms etc. then you will go with full blown deployment structure along these lines (used for big application deployed on multiple platforms):
  • /bin - startup scripts, rc3.d scripts, environment setup files, registry entries, etc.
  • /config - configuration files for app, should be possible to relocate to /etc by specifying env variable.
  • /logs - logs produced by app, safe to delete, config should allow us to move it to /var
  • /cache - temporary data produced by app, safe to delete, config should allow us to move it to /var
  • /data - data produced by application, config should allow us to move it to /etc
  • /lib - main application jar with all dependencies 
  • /lib/win86 - platform specific JNI libs for all supported platforms, selected by the start script, passed as -Djava.library.path=...
  • /lib/linux86
  • /lib/linux64
  • /lib/...
The main application JAR should have a Main-Class attribute starting the app and Class-Path attribute specifying the ordering of the dependencies (all located in the same dir). The Class-Path should start with the ../config path that will be used to load configurations and patch classes. This allows to keep the startup scripts simple.

The last layout allows you to run the application from your home, work all from /opt, or install in read-only /opt and put the configs and writable dirs under /etc and /var like a decent Unix application. The last option also allows you to run a few instances with separate configs and data from the same binaries.

Friday, October 22, 2010

Groovy Classpath Scanner

I just wanted a simple classpath scanner in Groovy - no library, no extra jars, no callback interfaces. I couldn't find any, so I wrote one. I'm posting it here and hopefully it would be useful to somebody. It is licensed under the established and permissive MIT License (if it precludes you from using it, let me know).

import java.util.zip.ZipFile
 
/**
 * <pre><code>
 * def cps = new GroovyClasspathScanner(packagePrefix: 'com.company.application')
 * cps.scanClasspathRoots(classLoader1) // optional
 * cps.scanClasspathRoots(classLoader2) // optional
 * ...
 * List<Class> classes = cps.scanClasses { Class it ->
 *    Event.isAssignableFrom(it)   ||
 *    Command.isAssignableFrom(it) ||
 *    it.isAnnotationPresent(MessageDescriptor)
 * }
 * </code></pre>
 */
class GroovyClasspathScanner {
  String packagePrefix = ''
  List<File> classpathRoots
 
  @SuppressWarnings("GroovyAssignabilityCheck")
  List<File> scanClasspathRoots(ClassLoader classLoader) {
    if (!classLoader) classLoader = getClass().classLoader
 
    def prefixPath = packagePrefix.replace((char) '.', (char) '/') + '/'
 
    def List<URL> urls = []
    for (URLClassLoader cl = classLoader; cl; cl = cl.parent) {
      urls.addAll cl.URLs
    }
 
    return urls
      .each { assert it.protocol == 'file' }
      .collect { new File(it.path) }
      .each { File it -> if (it.isFile()) assert it.name =~ /.*\.(?:jar|zip)$/ }
      .findAll { File it ->
        (it.isDirectory() && new File(it, prefixPath).exists()) ||
        (it.isFile() && new ZipFile(it).entries().find { it.name == prefixPath})
      }
  }
 
  List<String> scanClassNames() {
    if (!classpathRoots) classpathRoots = scanClasspathRoots()
 
    def classNames = []
    def collect = { it, String pathProp ->
      def normalizedPath = it[pathProp].replaceAll('[\\\\/]', '.')
      def packageRegex = packagePrefix.replace('.', '\\.')
      def classRegex = "\\.($packageRegex\\..+)\\.class\$"
 
      def match = normalizedPath =~ classRegex
      if (match) classNames << match[0][1]
    }
 
    classpathRoots.each {
      if (it.isDirectory()) {
        it.eachFileRecurse             { collect it, 'canonicalPath' }
      } else {
        new ZipFile(it).entries().each { collect it, 'name' }
      }
    }
 
    return classNames
  }
 
  List<Class> scanClasses(Closure predicate = { true } ) {
    return scanClassNames()
            .collect { try { Class.forName it } catch(Throwable e) { println "$it -> $e" } }
            .findAll { it }
            .findAll { predicate(it) }
  }
}

Saturday, September 18, 2010

Concurrent development

Background Story

That certain project was in its 4th year and after a few successful deployments in the US/LATAM regions, now the company was trying to push it to EU and APAC. The original developers were all in New York and over the last few months have been frantically working to adapt the product to EU's requirements (Asia was supposed to follow.) The scope was defined as 'whatever it takes', the methodology was a mix between 'trial and error' and bullying the users to contort the requirements to fit the delivered functionality. At the time, the EU team had realized that they would better spend their time staying on top of the changes and making sure the end product meets a minimum standard, so they were not really doing much development.

Time went on, requirements grew, scope shrinked. The project slipped past two deadlines and finally the Asia managers decided they need to take things into their hands and hire a local development team to avoid the communication gap that plagued the EU rollout and regain some control over the schedule. It was first time to have more than one people touching the code the core team was structured in a way that each component has an owner and the owner could do whatever they want. If you have a problem or need a change - ask the owner. The problem was not only that we were in different geographical location, in inconvenient timezone, but we were working on the same code, implementing requirements specified by separate BA teams, chasing schedules devised by separate project-management teams, and it all eventually converged in a common program-steering committee. I could go on, but suffice to say it was quite a mess - the bottom line is that moving from centralized sequential to distributed concurrent development models impose huge burden and the best advice one can give you would be "don't do it!".

Probably the biggest issue was that many people in the core team, just refused to change their way of working in order to accommodate our existence. Every second morning the trunk would not compile, often changes were checked in that prevent servers from starting, our changes were overwritten routinely because somebody's local modifications conflicted and they were unwilling to merge - you name it, we have it. The management layer was protecting them as "due to the years of accumulated experience, the productivity of the core team was much higher that ours, and the productivity hit they would suffer by addressing our petty complaints can not be justified in business terms". Luckily, there were some sensible guys and gradually we got to improve this, still I consider it one of the biggest organizational faults that for a long time the management efforts were focused on suppressing our complaints, rather than backing our suggestions on fixing the environment.

As the first QA delivery was approaching and the trunk was not giving any signs of getting more stable, we tried to think what can we do to stabilize the codebase. Some people said we should branch, others were weary of the cost of merging. The EU team had branched few months ago and all EU implementation were done on the branch and eventually (read 'sometimes') merged to the trunk. When the product was released in EU, they ended up with the problem how do they merge to the trunk. From what I hear it had been a terrible experience, including a lot of functionality rewrites, introduced bugs and regressions.

Knowing the EU problems and knowing that on one hand the trunk was still changing rapidly, on the other hand our requirements were dependent on code that was supposed to be delivered by US, we decided to branch, but keep developing on the trunk. All merges would be in direction trunk-to-branch and this would save us from the dreaded criss-cross merge conflicts. Since most of our problems to that date were with work-in-progress checkins, which we eventually wanted, we decided that we can treat the branch as a stable release line and trunk as unstable bleeding-edge code.

Unstable trunk + Release branch

I was tacitly elected as 'merge-master' and quickly I found myself following the same routine:

  1. Every morning I would pull a list of all the unmerged commits and review them in a text editor. Then would move each commit into one of these categories:
    • WANTED - changes that are required or prerequisites for implementing our business functionality. These should be always merged.
    • BLOCKED - changes that we DO NOT want. These should be always marked as merged (no actual merging, just mark, so they will not appear in the list next time).
    • IRRELEVANT - changes that won't hurt us, but we don't strictly need them. We were merging these in the initial stages as keeping the branch close to trunk makes merging easier, as we got closer to the release, we flipped the policy to improve the stability.
  2. When I merge or mark as merged the WANTED/IRRELEVANT/BLOCKED groups, I would put the category as a first word int he commit message. This made it easier to pick out the changes that were done directly in the branch (which should be kept to minimum and if necesarry ported manually to trunk). I didn't bother separating the individual changes, since the branch was not meant as a merge-source - this was saving me some time. Overall it was taking between 1 and 3 hours a day.
  3. There would be a number of changes that didn't make it to any of the categories. For these I was contacting the comitter and following up. Often it was work in progress, sometimes after clarification they would be categorized on the next day. Usually I would post this communication as a tagged blog-entry in our wiki. There was a page displaying all the entries tagged in this way.

I found out that sorting the changes first by user and then by date simplifies the review significantly. Turned out that TextPad macros can be a very powerful tool for things like this.

The release branch worked well for some time, until a major feature for the next release was implemented on the trunk. We blocked it and ever since then, every commit that touched this dreaded component had to be hand-merged. Often, merging an one-line change resulted in tens of conflicts, so we resorted to rolling back the file in question and manually porting the change. The worst thing is that we tested the trunk extensively, but the change in our release-branch received only cursory examination until it reached QA.

Furthermore, once we reached the second phase of the Asia roll-out, our team split and started to work in parallel on three staged releases, which were supposed to deliver unrelated functionality within 2 months of each other startin 6 months from the date. This meant that we need better mechanism for dealing with divergent codebase and big changes in progress.

Exchange-trunk + Development & Release branches per stream

After taking a step back, we came up with a new branching scheme that satisfied all our requirements. For each pending project phase we would create two parallel branches - development and release (we would call the combination of two branches a 'stream'). In addition, we devised the following policies and procedures:

  1. Developers always commit their code changes in the dev-branches.
  2. Any code committed to the dev-branch MUST compile. If the branch is broken, people should not commit further unrelated changes until the CI says it's fixed.
  3. Each commit in the dev-branch should contain work for a single feature. If there is certain code pertaining to two features, we pick one of them as primary and mark the other one as dependent in the issue-tracking system. Then, all the shared code goes to the primary feature and we know that we can not release the dependent on its own. It is not necesarry that the whole feature is committed in one go or that the dev-branch committed code actually works.
  4. When we need some code from a different stream, we would wait until they publish it to trunk and only then we would merge from trunk to the dev-branch. Cross-stream merges are prohibited. We were calling this 'picking-up' the feature. Pick-up changesets should be marked in the commit message.
  5. Each time we pick-up a feature, after we do the minimum conflict resolution, so the code works, we would commit the changeset immediately (that's the pickup changeset). This way, any additional enhancements, fixes. etc. will be committed in separate changeset, so it will be easier to merge them back to trunk later.
  6. Once a feature is complete and dev-tested on the dev branch, all related changesets for that feature are merged as one consolidated changeset in the release branch. We call this 'feature-promotion'. This practice makes creating release notes relatively easy and allows us to do cool things such as rolling back the whole feature with one command.
  7. When we promote a feature that has been picked from trunk, we immediately mark-as-merged this rel-branch commit into trunk to prevent double-merge conflicts. We would look if we have made any fixes on our branch and consolidate them into a single enhancement/bugfix changeset that will be merged directly from dev-branch to trunk (as in the the rel-branch we consolidate the pickup and enhancement changesets).
  8. If QA finds that the feature did not work, we would add further bugfix changesets to the rel-branch, but we would strive to keep them to minimum.
  9. When a release has passed QA, we would merge each feature-level commit that originated from this stream from the release branch to trunk ('publishing'). There it will be ready for picking up by the other streams (which will merge it in their dev-branch, promote it to release, etc).
  10. For each release we would tag the release branch, since it was already stabilized. Bugfix releases were just further tags on that same branch. For urgent production changes, we would create a bugfix branch from the tag (happened only a few times).

Overall it worked well for us. Few months after we addopted this scheme I moved to another company, but I really hope the process is still useful and being improved. An interesting thing is that every time I explain this, the first reactions are along the lines of "does it have to be that complicated?" And while I can agree that complicated it is, I am still to find a simpler streategy that could work on this scale. Any ideas?

Friday, January 15, 2010

Setting up PuTTY to use public keys for authentication

I've looked on the internet for a quick step-by-step guide how to get PuTTY to use public key authentication with OpenSSH daemon and it took me some time to figure. I'm posting these instructions in case anybody else has the same needs.

Prerequisites

Make sure that your OpenSSH configuration (usually /etc/ssh/sshd_config) contains the following line:

PubkeyAuthentication yes

In my case (CentOS 5.4) it was disabled by default.

Also, you would need the full PuTTY suite which can be downloaded form here (get putty.zip).

Generating the key

This is a way to generate the key with Putty. Alternatively you can generate it with OpenSSH's ssh-keygen tool and convert it to PuTTY format.

  1. Start PUTTYGEN.EXE
  2. In the parameters box at the bottom of the window, choose type of key 'SSH-2 RSA', set the bit size to 2048.
  3. Click the Generate button, move the mouse over the blank area until the progres bar fills up.
  4. Enter your notes in the comment line (this is displayed to you when you use the key, you can change later).
  5. Enter key-phrase, make it long and complex, write it down in a secure place or print it and hide it somewhere in your freezer.
  6. Save the private key (*.ppk) in a reasonably secure filesystem location. Even if somebody gets access to your private key, they will still need your passphrase to use it.
  7. Copy the text from the text box under the 'Public key for pasting into OpenSSH authorized_keys file:' and paste it on one line in a new file called authorized_keys (we'll use that later). The file should contain a single line terminated by Unix-style new-line and there shall not be an empty line after it.
  8. Close PUTTYGEN.EXE

Associating the key with your Unix account

  1. Login to your unix account
  2. Create a .ssh directory under your home if it does not exist
  3. Copy the authorized_keys file there
  4. Do chmod 700 ~/.ssh ; chmod 600 ~/.ssh/authorized_keys

This needs to be done for each machine you are connecting to. In this case it helps if your homw is NFS mounted.

Using the key directly

  1. Start PuTTY
  2. Specify user@host in the 'Session > Host Name' field.
  3. Specify the path to your private key file in the 'Connection > SSH > Auth > Private key file' box.
  4. Click the 'Open' button at the bottom of the PuTTY settings dialog.
  5. When prompted, enter your private-key pass-phrase and you will be logged in without entering your Unix password

Setting up Pageant to cache the decrypted private key

Let's look what we have done. The good thing is that our password does not travel over the wire and is not susceptible to man-in-the-middle attacks. The bad thing is that we used to enter the short and easy password of our Unix account, while now we have to enter the long and difficult pass-phrase of our key every time we establish a new Unix connection. In order to avoid this, we can use PuTTY Pageant which is SSH authentication agent (Unix equivalent is ssh-agent)

  1. Start PAGEANT.EXE
  2. Click on the computer-with-hat icon in your system tray.
  3. Choose the Add Key option and pick your private key (*.ppk)
  4. Enter your pass-phrase
  5. Close the pageant dialog

From now on, when establishing SSH session Putty will try to use the decrypted key from Pageant first and then fall back to password auth if none of the keys match.

You can create a shortcut, starting Pageant and passing the paths to your keys as arguments. This will start Pageant and load the keys in one step, but you will still need to specify the pass-phrase every time you do this (typically after system restart).

Keep in mind that Pageant holds the private key in memory unencrypted. If anybody captures a heap dump of the process, they can get access to your private key without knowing the pass-phrase. That's why, you might want to stop the Pageant if you are not using it for a long time or if you shae the machine in multi-user environment.

If using Pageant, you might also check the Putty option 'Connection > SSH > Auth agent forwarding', which will allow you to use your key from the remote machine on which you are logged on.

How fast an SSD drive do you need

If you need Intel X25-E 32G SSD for 70% of the cheapest listed price (shipping extra), please let me know.

For a long time I thaught that the bottleneck of all builds was the HDD, so when I got my new notebook, the first thing I did was to add a spiffy extra Intel X25-E SSD hard drive to it. As I expected, the builds went much faster. To my surprise, the HDD throughput stayed fairly low during the build, which suggested that the benefit of SSD drives kicks in early and buying higher grade drives doesn't make much difference as the bottleneck moves to the CPU quite quickly. All this makes sense, considering that a typical application has hundreds to thousands of files and the HDD spends a lot of its time seeking rather than reading.

When I cleared the IntelliJ IDEA caches and opened the IDEA Community project (total 900MB, 66k files), during the indexing, one of the cores stayed pegged, the HDD read throughput did not exceed 4mb/s for 4 mins then for 1 minute it rose to top 25mb/s, avg I guess around 15mb/s. The write never exceeded 10mb/s, and for most part it was bellow 4mb/s, the last minute was between 5 and 7mb/s.

During initial compilation, the 2 cores of the CPU (2.53GHz T9400) were quite busy, staying above 80% all the time, the disk utilization during compilation stayed less than 4mb/sec with the ocasional peaks at 6mb/sec. The write peaks were 5mb/sec, for the most time bellow 1mb/sec.

At the end of the compilation, the index update took 50 seconds, with average read throughput ~10mb/s, peaking at 30.5mb/s, the write peaked at 7mb/sec. During that time the CPU utilization dropped around 50%, which only shows that IDEA's indexing is not using both CPUs.

The bottomline is - it's not worth byuing expensive SSDs for consumer usage - cheaper ones are just as good for the average home and software development workflow. Most of the applications do not involve transferring huge volumes of data and the slowness of the spinning-platter HDDs is mostly because of seek times and fragmentation. Expensive SDDs are warranted if you are working extensively with media files or are processing huge amounts of data on the disk.

Saturday, November 14, 2009

Adding custom handler for JMX service URLs

Recently, I've been creating some wiki pages describing the JMX management capabilities of the system I work on and I found it quite annoying to use the MX4J HTTP Connector or copy and paste the huge-ass service:jmx:rmi:///jndi/rmi://host:port/connector URLs, so I dug in MSDN, waisted some time and without further ado, I present you:

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\SERVICE]
@="URL:Service Location Protocol"
"URL Protocol"=""

[HKEY_CLASSES_ROOT\SERVICE\shell]
@="open"

[HKEY_CLASSES_ROOT\SERVICE\shell\open]

[HKEY_CLASSES_ROOT\SERVICE\shell\open\command]
@="\"C:\\Program Files\\Java\\jdk1.6.0_06\\bin\\jconsole.exe\" %1"

Copy the text in the box above, paste it in Notepad, edit the blue text to point to your latest JDK, save as service-url-handler.reg and doubleclick to merge in the registry. If you make a mistake, rinse and repeat.

Once you are done, your can use HTML like this:

<a title="Static Data Server" href="service:jmx:rmi:///jndi/rmi://prodhost0123:9002/jmxrmi">manage SDS</a>

On clicking the link, the browser will open JConsole for the specified service URL.

Monday, January 12, 2009

The other half of the puzzle

This post on service service granularity from Ross Mason (the original developer of Mule ESB) got me in retrospective mode. I've been thinking about this before and with the time, I have come up with some criteria how to break functionality into services. Unfortunately that turned out to be only half of the puzzle. The other half is the implementation and maintenance strategy that would allow you to achieve your nicely layered boxes-and-arrows vision, while delivering ROI on quarterly intervals and not falling into the JBOWS or stovepipe-system pitfalls.

I personally favor starting top-down, focusing on specific applications and task-level services, and harvesting entity and utility services from working production code. The downside of this is that it is generally more work, often seen as 'tinkering' and in case we consolidate utility code from multiple systems, will likely introduce temporary instabilities.

This makes it a difficult sell to management - what they see is the IT guys trying to get budget to work on some kind of metaphysical inner-beauty thing instead of delivering new features. Saying that this would reduce bugs is not a great argument, because you will be reminded that's why we pay the QA team and by the way, as a professional you are not supposed to write bugs in the first place.

On the other side, the PHBs of the world seems to love the idea of the Centers of Excellence, located in China or Malaysia, full of trained and cheap labour, building the utility services and coding the entity diagrams designed by the Architecture Group in their ivory tower, while the solution engineers use point and click tools to churn 'codeless' composite applications. Unfortunately this breaks at the other end - unexpected interactions are discovered at deployment time, maintenance takes too long as the whole turns out to be more than its parts, exhibiting "emergent behavior" (also known as "underspecified features") left and right.

So, there is no quick and easy way. I guess we need to become IT salesmen and we need to compete with the professional vendor scamsters and the consultancy loan-sharks (that's a topic for another post).

Thursday, October 30, 2008

Mavenizaton - A real life scenario

The other day I posted a message on a certain vendor’s support forum asking about the possibility to include minimal POMs in their jars (so they will be easier to mass-import into local repository) and I got the following reply:

We want to move from ant to maven for a long time but never got a chance to do it. Our ant script is pretty big and complex so we are afraid it will take us a while to migrate to maven. Since we have other important things to work on, we keep delaying this kind of infrastructure things that have relatively less impact than bugs. If you know any way to migrate from ant to maven quickly, I would love to hear.

So I asked if I can get access to their Ant script and they kindly sent me that 3000-lines of a beast.

The Challenge

The product is comprised of several modules which have well-defined dependencies on one another and can be used in various configurations. Each configuration is described in a build.properties file by xxx-source-path, xxx-properties-path and xxx-output-path properties. The source-path contains both Java files and misc. resources (there are no tests). The xxx-properties-path contains property files only.

In the end, for each module the build produces the following artifacts:

  • JAR files – depending on properties, these can be:
    • Obfuscated with Zelix KlassMaster
    • Debug builds (still obfuscated, but with line-numbers)
    • Postprocessed by Retroweaver for Java 1.4 compatibility
  • Zipped sources
  • Zipped source stubs – public and protected method definitions and javadoc (no method bodies)
  • Zipped Javadocs
  • User manual in PDF format

In addition to these primary artifacts, the project:

  • Generates a couple of demo applications packaged as single-click JARs and JNLP.
  • Filters all property and some source files, substituting placeholders with values defined in the build.properties.
  • Compiles on the fly a doclet and then uses it to generate the source stubs.
  • Creates a bunch of bundles, containing different combinations of the aforementioned artifacts.

The vendor has a policy of releasing new demo-build every day which expires after 28 days.

The First Step – Fake It

In fact, we, the customers don’t care whether you are using Maven internally. All we care is to receive a POM with correct dependencies and (if possible) to be able to download the libraries from the official Maven repository (a.k.a. Repo1) or if not – your private repository (i.e. http://repo.your-company.com/demo or http://repo.your-company.com/licensed ).

In order to achieve this:

  1. For each artifact, create a pom.properties file containing 3 properties: version, groupId and artifactId.
  2. For each artifact, create a minimal POM containg the artifact group, name, version and dependencies information. Alternatively you can put placeholders and use Ant filtering to resolve the group/name/version from the pom.properties
  3. Integrate the new files into your build process, treating them as yet another resource file and placing them under the META-INF/maven/your/artifact/group in each artifact JAR.
  4. If desired use artifact:deploy task to push the artifacts to a Maven repository.

This is all you need to do for the ‘regular’ JARs. For the various other files, you would want to use the same artifact name and a classifier I would suggest using:

  • sources – standard Maven convention, since the full sources are not released to regular customers, it would make sense to have them either under a different classifier (e.g. fullsources) or same classifier, but from a private repo
  • javadocs – standard Maven convention
  • jdk14 – for retrozapped binaries
  • debug – for obfuscated binaries with line numbers

Then you Migrate

If we step back, the current build proces is something like this:

  1. Preparation Phase
    1. Set variables
    2. Compile custom doclet
  2. Generate Sources
    1. Filter particular files to resolve values from properties
  3. Compile
  4. Copy resources
  5. Package binaries (create jar file)
  6. Obfuscate
  7. Retrozap
  8. Javadocs
  9. Source Stubs
  10. Assemble distribution archives
  11. Build the demos

Here is how it would look after we convert the build to Maven:

  1. All the path variables go away, replaced by standard Maven directory layout (you should be able to reorganize the source trees for a few hours on a Friday afternoon.) As a last resort you can define custom directories in the build section.
  2. The company-name, version, etc. props go away replaced by the respective POM elements.
  3. The rest of the settings are specified in profiles defined on project or user level.
  4. The resource filtering is a built in feature for maven, but if you need to pre-process Java files, you would need to attach your own plugin to the grnerate-sources lifecycle phase.
  5. Compile and Package are standard Maven targets and you don’t need to do anything.
  6. The ZKM obfuscation would be tricky because there is no Maven plug in (or at least I couldn’t find any). I suggest that you use the AntRun plugin as a temporary hack.
  7. The Javadoc plugin would automatically generate your Javadocs, you need to explicitly specify a second execution for your custom doclet
  8. The assembly plugin should help you organize your different distributions.

This leaves out a lot of details, but ultimately some of the decisions are yours to make. I would suggest using a script to reorganize your sources, so you can do a number of dry-runs and verify that the result is as expected before you change the script to perform the move in the version control system.

Project Layout Considerations

Each Maven POM has exactly one parent, but can be part of multiple reactors. Both parent and reactors are pom-packaged artifacts, but their role is different. Most tutorials use the same pom for both purposes, but there is benefit in separating the functions (more about this in a bit).

POM Inheritance

The role of the parent is to provide defaults for the child POMs that inherit from it. The POMs are resolved by the normal Maven dependency resolution mechanism, which means that if you want the child projects to reflect a change in a parent-pom, you need to install/deploy the parent first. Alternatively, you can use the project/parent/relativePath element to explicitly specify the parent-pom’s path in the file layout (in this case, the changes are picked from the file-system.)

At the top-level parent you should use dependencyManagement to specify versions and transitive-dependency-exclusions for all artifacts used by the project. No child-artifacts should explicitly declare versions and exclusions.

You should use pluginManagement to fix the plugin versions and (optionally) specify common options for plugins. It’s ok (although not recommended) to override the plugin options in the children-pom’s, but you should not specify versions there. If you need the same overrides in multiple children, consider extracting them into intermediary-parent pom.

Finally, you should try to specify most of your profiles on a parent-pom level. This, combined with the pluginManagement allows you to define the bulk your build in the parent and leave the children DRY.

The children have to explicitly specify the master-pom version which makes it a bit of a pain to increment the version (on the other side, the master-pom usually changes much slower.)

Building in Dependency Order

The normal way for Maven to resolve dependencies between projects is through the local repository. This means that if project A depends on project B and we make a change in B, in order to test A against the new change, we need to first install or deploy B and then build A, so it would pick up the new changes (this is assuming we’re using SNAPSHOT versions).

The reactor projects take care about such closely related artifacts and automatically rebuild them in the correct order. Also they act as a grouping for the sub-projects (useful when you build assemblies). The reactors themselves are artifacts using pom-packaging (same as parents), but they explicitly list the relative path to each constituting module, and this is the reason that I recommend separation between parents and reactors:

Creating Distributions

The standard way of packaging distributions in Maven is using the Assembly plugin . It allows you to describe your distribution package in terms of project resources, artifactsIds and classifiers. A typical assembly descriptor would be:

  • Create a tar and zip files with classifier ‘distro’.
    • Add all files from /src/main/assembly
      • excluding **.xml, and **.sh.
    • Add all files from /src/main/assembly
      • that match **.sh
      • and set the unix permissions to 551.
    • Add the maven artifact
      • with group-id=com.company.product.modules and artifact-id=module1 and classifier=obfuscated
      • put it under lib.
    • Add all the transitive dependencies of this project (assuming this descriptor is in a reactor project)
      • and put them under lib/ext

You can also unpack and consolidate JARs, specify manifest-entries and signing for single-JAR distributions and so on.

Each artifact can produce more than one assemblies. If you want your assemblies to go into the repo, make sure you use the ‘attached’ goal. Most of the times, I use the reactor poms for distributions, but sometimes I just define the assembly in the JAR module’s POM.

Parents and Children vs. Reactors and Modules
Category Parent/Child Reactor/Module Merged Parent+Reactor
Direction of Coupling Children know the names of their parent, parents don’t know their children Reactors knows the locations of their modules, modules don’t even know whether they are being built as a part of a reactor Creates circular dependency between children/modules and parent/reactor artifacts.
Multiplicity Each child has exactly one parent, specified in the child POM. A module can be part of more than one reactors. You must keep it to one reactor. If you define alternative reactor, the parent will still be resolved to the main parent-POM (as specified in the children POM’s), which can lead to a great deal of confusion (and undefined behaviour for some plugins).
Location The parent is usually resolved through the repo (optionally through relative path) The modules are always resolved through relative path You need to physically layout your project, so the parent POM is accessible by relative path (which is not needed otherwise).
Change Drivers The parent changes when your build process changes. The reactor changes when you add a new module By the artificial coupling, your POM is subject to more change. This is particularly bad for the parent role, because you need to manually update the parent-versions of the children.

Given this table, I’d recommend a project layout along these lines:

-+-+- project-root/
 |
 +-+- modules/
 | |
 | +-+- module1/ 
 | | |
 | | +--- pom.xml       | inherit from modules parent; specify dependencies 
 | | |                  | and module details (name, version, etc.)
 | | +-+- src/
 | |   +-+- main/
 | |   | +--- java/
 | |   | +--- resources/
 | |   |
 | |   +-+- test/
 | |     +--- java/
 | |     +--- resources/
 | |
 | | 
 | +-+- module2/ 
 | | |
 | | ...
 | |
 | +-+- module3/
 | | |
 | | ...
 | |
 | +-+- reactor1/       | e.g. all modules - used for the CI build and pre-commit
 | | |
 | | +--- pom.xml       | no parent; specify the modules as ../module1, ../module2, etc.
 | |
 | +-+- reactor2/       | e.g. only module2+module3 - used by the module3 developers only
 | | |
 | | +--- pom.xml   
 | |
 | +--- pom.xml         | modules parent - inherits from the main parent pom and specifies 
 |                      | module-specific profiles and plugin settings
 |
 +-+- applications/
 | |
 | +-+- application1/ 
 | | |
 | | +--- pom.xml       | inherit from apps parent; specify dependencies, module details 
 | | |                  | and whatever custom steps necesarry for the application
 | | ...
 | | 
 | +-+- application2/ 
 | | |
 | | ...
 | |
 | +-+- reactor/        | e.g. all applications
 | | |
 | | +--- pom.xml       | no parent; specify the modules as ../application1, ../application2, etc.
 | |  
 | |
 | +--- pom.xml         | apps parent - inherits from the main parent pom and specifies 
 |                      | module-specific profiles and plugin settings
 |
 +--- main-reactor      | specify as modules ../applications/reactor and ../modules/reactor1
 |
 +--- pom.xml           | the main parent pom

A few Tips

When You getStuck with a Bad Plugin

For all operations that you can’t easily achieve with the existing Maven plugins, you can fall back to the Antrun plugin and reuse snippets of your current build script. Yes, it’s a hack, but it gets the job done and you can fix it when it breaks.

Try to keep these hacks in the parent pom.

Dependency Management

When you define dependencies, take care to specify proper scopes (default is ‘compile’, also you should consider ‘provided’ and ‘test’). You should also mark all optional dependencies like POI HSSF. For some artifacts you might need to specify dependency-excludes, so Maven doesn’t bundle half of the Apache Commons with you.

Evaluation Builds

You might want to release the daily evaluation builds as snapshots. Maven has specific semantic for snapshots that it always refreshes them based on timestamp. For example, if you release an artifact my.group:module:1.0.0, Maven will download it once to the local repository and never look for another version unless you delete it manually (that's why you should NEVER re-cut a release once it's been pushed out - just declare the version broken and increment).

If you use a snapshot version (i.e. my.group:module:1.0.0-eval-SNAPSHOT), Maven will check once a day (unless forced with '-u') and automatically any new version base on timestamp. To achieve this you might want to cut an eval-branch from the tag of each release and change the version using a shell script or something.

Saturday, October 25, 2008

Why ORM?

I like Spring JDBC Template - it is simple, clean and saves a lot from the JDBC drudgery. It provides nice abstraction, simplifying the usage and management of prepared statements and overall if all you want is to do an ocasional query, it doesn't get any simpler. Oh, and you have full control on the underlying JDBC connection, allowing you to exploit any vendor-specific functionality. The provided functionality only makes the data access easier and supports only very basic property to column mapping out of the box (or you can write your own mapper in Java). Because of its lightweight nature, JDBC Template does not allow for transparent caching, horizontal table partitioning, vertical sharding, etc. It also doesn't offer lazy fetching of relations, identity tracking and other instrumentation magic.

Another tool I like is iBATIS. In comparison with JDBC template, it offers more structure, organizing my SQL statements in a logical way and supports most common forms of mapping the result sets to beans (including graphs of objects and joins). Ibatis does support caching (only on a whole query level), still no sharding and partitioning, lazy fetching and identity tracking. IBATIS doesn't try to parse your queries.

The Abator tool can generate iBATIS CRUD mappings, DDL from object model, and object model from a database, but frankly - in its generated form all these suck. The DDL uses only a few datatypes, has no RI or semantic constraints, nor indexes (I use it sometimes, but only as a boilerplate which I extensively tweak afterwards). The generated beans are isomorphic with the underlying tables, which is great if you are doing CRUD, but I find that most of my applications do data analysis, so the queries tend to be quite hairy, half of them encapsulated in stored procedures (for transaction processing I'd rather use Spring or plain JDBC anyway). The bottom line is that Abator handles the trivial cases, but for most of my projects it doesn't help much, so I'm back to manual coding (which is not that bad anyway.)

The first time I looked at ORM was when I checked TopLink for a project around 2000. Back then I got the impression that it introduces a lot of new concepts in order to simplify something that's already simple enough - loading a couple of beans from a table. For that project I used plain JDBC, it took me perhaps 20 mins to write and I can't remember taking much time to maintain that code - the total cost should have been less than 3 man-hours.

The second time I tried Hibernate and Toplink last year (2006) on a prototype with the same dataset and relatively small domain model (for which I finally ended up using iBATIS). The first thing that stroke me was how slow everything was - the startup time was noticeably slower than with iBATIS (about 500-800%), spent in initializing the JPA entity manager and the queries were consistently 30-50% slower. It might have been that I didn't know how to tune it, but I just couldn't achieve satisfactory results. I researched the facilities for mapping to externally defined schema and it stroke me that both Hibernate and TL are way clunkier than iBatis. There were also a number of restrictions that suggested that I need to modify my schema just to enable certain features of the tool... in the end, the identity tracking is a leaky abstraction - the whole story with the attached and detached entities smells to me.

Now the thousand dolar question, given that most applications out there DO NOT use horizontal partitioning or sharding, caching in the application layer is usually more efficient anyway, identity tracking and the transparent (hidden) lazy fetching often causes more problems than it solves (and countless hours lost in app tuning with dubious results), why are so many people obsessed with the idea of cramming an ORM into their application?

The other day I wrote a small application that had four composite entities and a couple of fairly sophisticated queries, the the data access part took me about less than an hour (that's implementation, testing and tuning), so:

  • How long would it have taken me if I used JPA? (to get reasonably well performing, tested code)
  • If you are using ORM, how many entities do you have? How much time (percentage) do you spend working on your persistence logic? Are you using the database as operational storage or are you trating it as a long-term asset? Do you share the DB with other applications?
  • Are the productivity gains realized only when your persistent model is so big that it's unmanageable by other means? Is it to futureproof a product (what is a reasonable timeframe for ROI, any examples?)?
  • How important is for you the ability to scale your data access to multiple database servers?
  • Have you ever switched an application from one SQL server to another? How much effort was it? What does the application do with the DB?
  • What are the benefits of using ORM smart caching and partial queries in comparison with in-memory database like TimesTen or H2?

Please enlighten me...

Wednesday, September 10, 2008

On Scopes

Let's define component as a programming abstraction that exposes a number of interfaces and is instantiated and managed by a container. A component has implementation that sits behind the interface and provides the functionality, which could be a custom Java class, a proxy, a BPEL engine, a mock object, or even a mechanical turk solving captchas.

In the case of Java class components, they are usually composed of smaller Java classes like the ones in java.lang.* and java.util.* packages. All but the most simple Java objects are actually object graphs which are instantiated, wired togerher and orchestrated by the Java language and the JVM. The Java language specifies the composition structure and behavior, while JVM provides the means to invoke operations and share data. In contrast, the components are instantiated by a container and the container is responsible to wire them together (usually based on a blueprint in the form of a configuration or class annotations). The container can also provide a number of declarative services to its components: transaction management, access control, performance statistics and transparent distribution. Some popular containers are OSGi, Spring, EJB, ActiveX, MTS/COM+.

Even if a container can expose a local component over remote interface without requiring any code changes, practice has shown that taking a single-server application and distributing it in such fashion usually results in a disaster. This doesn't mean that the non-invasive distribution support is useless though. Given responsible usage, it can enable you to build distributed applications without having to deal with the transport API, using clean and reusable code (POJO). There are a number of new frameworks that are built around the concept and try to provide the right level of transparency and control (Mule ESB, Spring Remoting, Spring Integration are some popular choices).

Once you get too many components in the same contaner, autowiring starts doing most unexpected things, debugging becomes difficult and you start loosing track of your system. The solution is to add scoping. Spring supports limited scoping facilities in the form of parent-child application contexts. Although it solves the problem with configuration visibility, it does not provide facilities for controlling the public interface of the scope (explicitly exported objects). OSGi tackles this problem from a different direction using controlled classloaders, Spring OSGi is trying to be the best of both worlds, giving you scoped configuration and runtime autodiscoverable scoped components.

<interlude/>

I just finished reading Distributed Event Based Systems and they have an excellent chapter on utilizing scopes as means to structure a distributed event-driven application (chapter 6). They suggest a scoped architecture, where each component can belong to multiple scopes, scopes are linked in an arbitrary graph and notifications are governed by the different scope and component properties. The scopes described can declaratively provide a number of services (think AOP for messages). Some of these services are:

  • Containment - logical grouping of components and other scopes, allowing easy addressing for event dissemination and policy enforcement.
  • Scope Interface - defining which messages can cross the scope boundary and enforcing this policy
  • Transmission policy - determine which scope components will receive a certain message and/or which components have a right to publish/receive messages that cross the scope boundary.
  • Mappings - when a message crosses the scope boundary, enrich or transform it based on the source and destination scopes.

Scopes could be used to delineate groups with different QoS requirements, or to partition the application in geographical or security domains (or even both at the same time) and apply the appropriate policies. Integrating an external systems is also easier, because they are treated as yet another scope (as opposed to "enemy in the bee's nest") and you can provide rich access to the messages that the third party is entitled to without having to bolt on yet another authentication and authorization mechanism.

The book focuses in great detail and implementation strategies, analyzing different approaches ranging from simplistic (flooding) to very complex (integrated routing). Right now, the described architecture can not be implemented directly in any eventing system that I know of, though we can see some of the ideas in Jini (peer to peer with cooperative filtering), JMS (in implementation supporting topic hierarchies), OSGi (intra-JVM) or SCA (a lot of talk about scopes and composites, but I don't see them doing anything useful with them). The authors also propose a configuration language for managing scoped systems with the specified features. I can see AMQP as a flexible low-level specification that would allow to build something like this by implementing custom exchanges. We can use the scope configuration language as an intermediate representation, from which we can generate the custom exchange code.

Ultimately, I believe that in 10 years from now this scoping and routing facilities will become standard part of the messaging middleware (and perhaps hardware?) I'm looking in the general direction of AMQP, possibly SCA (despite their WS-* fetish) and new high level languages directly expressing architectural concerns like ACME and Einstein.

Tuesday, September 2, 2008

Dynamic components in Mule

Imagine that you are given to implement the following scenario:

  • A system is composed of a number of uniform entities, each entity publishes its status on a separate pub-sub topic and accepting instructions over separate control queue.
  • Your application receives a stream of instructions over a control channel, instructing it to monitor and control or stop controlling certain entity.

or you receive a stream of active orders and want to subscribe to the right marketdata to calculate a relative performance benchmark, or...

Usually I write about how to implement stuff with Mule, but this time I'm going to write why Mule might not be your best choice if your use-case is anything like above.

The most straight forward approach for implementing the system above is to create a simple POJO, encapsulating the management algorithm and have a service listen to the control channel and instantiate/dispose a new component for each managed entity.

The problem is that in Mule the components are somewhat heavyweight and it's not so nice when you start having hundreds (approaching thousands) of them. Another problem is that the code for manually creating and registering a componment along with the whole paraphernalia of routers, endpoints, filters and transformers is quite verbose.

The latter problem is easier to solve. There are a couple of JIRA issues that aim to simplify the programmatic configuration (MULE-2228, MULE-3495, MULE-3495). The Annotations project at Muleforge is also worth watching (right now there's no documentation, so you'd need to dig in Subversion).

The problem with the too many components is more fundamental. The main application domain for Mule is service integration. Though it also happens to be a fairly good application platform, it does fall short when it comes to managing a lot of components. One of the important things missing is the ability to create groups of components with shared thread pools. Another missing thing is better support for variable subscriptions (provide an API to easily add and remove subscriptions to the same component using some kind of template). Another notable improvement would be to elaborate the models into full blown scope-controllers, allowing to create composite applications with proper interfaces, routing policies, etc. All of these are addressable, but there is a long way to go.

There are also some improvements that can be done to the JMX agent - use JMX relation service to connect component to its endpoint and statistics, all components of certain type, user defined groups of components. Allow the component to exercise some control over the Mule-generated ObjectName so users can organize the different components in groups and ease the monitoring by EMS tools by allowing to query the parameters from a specific group.

Please share if you've had similar issues, how you dealt with them and whether you think {with the benefit of a hindsight) that the solution was worth the effort. Also I'd like to hear from users/developers of other integration frameworks or composite application containers (Newton?) how they handle these problems.

Monday, September 1, 2008

Transformers vs. Components - Take 2

In my previous article, I claimed that one of the main criteria for which Mule artifact to choose is the multiplicity of the inbound and outbound messages. I've been thinking about it and I want to add two more points:

  • Transformers are one instance per endpoint reference. This means that even if you use pooled components, all messages go through single transformer instance. In such case, you need to make sure that the transformer is threadsafe (which is not true if it is holding a JDBC connection or Hibernate session). The components do not have to be threadsafe, though if you are injecting some shared state you still need to properly synchronize the access to it.
  • Mule2 services allow you to configure different ways of instantiating the component (singleton, pooled, looked up from Spring/JNDI/OSGi/etc.). In contrast, all transformers defined using the mule-core namespace are prototype-scoped.
  • I actualy agree that direct database access belongs in a component. I still think that accessing a cache is kindof a gray area though.

Saturday, August 16, 2008

InfoQ, Firefox Hacks and Media Snobbery

I happen to be one of those people that don't like TV - it's not that I don't watch it when I get a chance, but I've made a conscious decision not to buy one and to get my news and movies from other sources. My primary issue is that TV as a media is too engaging, passive and slow. Radio is also passive and slow, but less engaging, hence better.

For example: in 10 mins browsing news sites, I can learn more than 10 mins of browsing newspapers, which still fare better than 10 mins of radio, which is just the same as 10 mins of TV, except that when I watch TV I don't do anything else.

I'm a much faster reader than listener. When I read I can always stop and mull over a sentence for a couple of minutes, go back or skip forward with natural ease. Not so with video and audio. Even though most streaming media these days have some kind of non-linear controls (skip-bar, etc.) it's still impossible to do the equivalent of scanning the headlines or speed-reading in the case of podcast or video content.

One of the reasons I like the InfoQ interviews is that they have full transcripts. One of the resons I hate them is that the transcript is enclosed in small box, 250px high in the middle of the screen and one has to click the open and close buttons and scroll like crazy. What I often end up doing is to fire DOM Inspector, cut off all the DOM nodes except the ancestors of #interviewContent, switch to CSS properties, delete the height and max-height props and this way I end up with full-screen view of the transcript, which I can print or browse at my convenience.

Today as I was debugging some stuff, I remembered that Firefox supports user stylesheets. By putting the bellow statements in my ${FIREFOX_PROFILE}/chrome/userContent.css, I was able to expand the transcript to be readable in a browser without inner scrolling and tweak the printable view to display only the relevant content (no empty squares in place of the flash player or vendor links I can't click on paper.)

/*
 * This file can be used to apply a style to all web pages you view 
 * Rules without !important are overruled by author rules if the author sets any. 
 * Rules with !important overrule author rules. 
 * 
 * For more examples see http://www.mozilla.org/unix/customizing.html 
 */ 
 
div#interviewContent, 
div#interviewContent * { 
    height: auto ! important; 
    max-height: none ! important; 
    overflow: visible ! important; 
} 
 
div#interviewContent div div div { 
    display: block ! important; 
} 
 
@media print { 
    * { 
        border: 0px ! important; 
        float: none ! important; 
    } 
 
    #content, 
    #container, 
    #content-wrapper, 
    .box .bottom-corners, 
    .box .bottom-corners div, 
    .box .top-corners, 
    .box .top-corners div, 
    .box .box-content, 
    .box .box-content-2, 
    .box .box-bottom, 
    .box .box-content-3 { 
        margin: 0 ! important; 
        padding: 0 ! important ; 
        float : none ! important; 
        width: 100% ! important; 
        line-height: 130% ! important; 
    } 
 
    /* these don't work on paper */ 
    object, 
    .comments-sort, 
    .vendor-content-box { 
        display: none ! important; 
    } 
 
    /* visual garbage */ 
    .tags3, 
    .comment-reply, 
    .comment-header > p, 
    .comment-footer, 
    #interviewContent img[alt='show all'], 
    #interviewContent img[alt='hide all'], 
    #content-wrapper > .box > h2, 
    #footer { 
        display: none ! important; 
    } 
 
    /* Fix comment headings */ 
    .comment-header * { 
        display: inline ! important; 
    } 
 
    div.comment-header { 
        border-top: 1px solid gray ! important; 
    } 
 
} 
Now the only thing left is to convince the InfoQ guys to start providing transcripts for the presentations and downloadable slides :-)

Wednesday, July 23, 2008

Transformers vs Components

When I started using Mule, for some time I used to wonder what's the big difference between a transformer and a component. Why don't we just stick with the plain pipes and filters model and we complicate it with the 'component' concept?

In general, transformers have conceptually simpler interface - they are supposed to get a payload and return a payload, possibly of different type. You should prefer transformers for reusable transformation tasks. On the other hand, transformers can not:

  • Swallow messages - to achieve this use filter or router.
  • Return multiple messages - use router.
  • Pause temporarily

In addition, despite their more complex configuration components provide some neat features:

  • Message queuing - if your message goes through multiple stages of enrichment, each taking variable time, you might be better off implementing the stages as components and separating them with VM queues.
  • Statistics - automatically measures the processing time and volume through each in or outbound endpoint.
  • Lifecycle control - you can start, stop or pause component multiple times (while a component is not running the messages will queue up.) The transformers are only initialized and disposed once.
  • A componen allows you to tack on multiple filters, transformers, routers, etc. A transformer is one part of this chain.

To put it together, here is an overview of Mule's component roles in a simple message routing sequence (I'm trying to explain the roles, not the exact sequence.)

  • The message enters through an inbound endpoint, where the transport extracts the payload and the message headers and bundles them in a message. (The message and some other objects are bundled in EventContext, but it is still a mystery to me why do we need it.)
  • After the message is created it passes through a filter chain, where the filters are applied one after another and each of them votes with true or false a full consensus is required or otherwise the message is rejected. Depending on the config the rejected messages can be routed somewhere else. The filters are not supposed to modify the message (in practice they can, but it's a very bad idea.)
  • If a message passes all filters it goes through a transformer chain, where each transformer is applied to the output of the preceding one. A transformer is not able to gracefully reject a message, but it can throw an exception.
  • We might have an interceptor wrapped around the component, which can log stuff before or after invocation or measure latency, etc.
  • Based on the payload and on the component type, Mule resolves the method it should call and if necessarry transforms the payload to something that fits. The return value of the method is used as a payload to a single outgoing message.
  • The outgoing message is passed to an outbound router, that can split it in multiple messages or just drop it. The router then usually sends the message(s) to arbitrary number of outgoing endpoints. The outgoing router uses the filter chains of the outgoing endpoints to decide which ones to use. The outgoing endpoints can be Mule internal endpoints or periphery endpoints, conecting the application to external system.

In general, I would recommend that you start with transformer and refactor it to a component if you realize that you want to add any of the aspects mentioned above. You can even easily use transformers as POJO components.

Monday, July 21, 2008

Testing Mule applications

Antoine Borg has posted an intersting article at Ricston Blog about the feasibility of using mock objects for testing Mule applications. The bottom line is that in integration scenario is usually difficult to capture the application specification in mocks and often it's easier to write stub applications simulating the external systems (outside of your application process).

I've found that often I don't really test the whole application, but instead I test single components with a few attached transformers, filters and routers. I start by writing a simple Mule configuration - a single component using VM endpoints with queuing. Then I use MuleClient to feed in canned input data and assert the output from the outbound endpoint(s). As the application takes shape, I add transformers and routers as needed to approximate the real usage.

I could imagine that the next step would be to reuse my production configuration and extract the perimeter endpoint definitions in a new file (separating them from the model, connectors and internal endpoints) and pass the two configuration files to the config builder. This would allow me to create an alternative perimeter endpoints file using VM endpoints, so I can instantiate it in test case and use MuleClient for testing.

The benefits of the approach are that you are testing your component and routing logic and are not exposed to the peculiarities of the external system. Ideally we still want to have a full integration tests, including ones covering crash-failure, failover, connectivity loss and overload scenarios. We can achieve parts of this by stubbing the external system, but so far I usually find it difficult to reproduce the behaviour faithfully enough (especially when we have limited understanding about the external system).

No bulletpoints this time.

Monday, June 16, 2008

Build, Buy or Steal

This post is based on a text I wrote at my day job. It is edited to reflect my personal opinions and does not represent my employer’s view in any way.

The classic 'build vs. buy' dilemma is further complicated by the new wave of quality open source components.

Even if we assume that the open-source alternatives are generally inferior to their closed-source counterparts, their low price makes them an attractive choice for getting started, provided that there is an easy migration path to more powerful solutions. Additionally, many open-source tools are backed by commercial companies which can provide support, consulting and guidance on demand.

Open-source components are often (not always) higher quality than the internally developed libraries. This is because of the usually pretty-good community QA (many users; no time pressures) and the small-vendor mentality of the backing firms (they need to be much better than the industry standard in order to convince a client). Also, a solid OS project provides a decent documentation and community support, often has books written about it and, in general, makes it easier to recruit people already familiar with it.

We do want to build components in-house when we believe that we can provide and need more value than their OS and commercial counterparts can provide. We always need to keep in account that building good library is a continuous investment in new features, bug fixing and documentation. Providing a sub-optimal internal component is the worst of all worlds.

Another big question when to contribute our changes back to an open source project. Conventional wisdom says that you shouldn't give our work for free. Still, given the previous paragraph, I would claim that it's in our best commercial interest to contribute back any changes to the external module's core. In such cases, the initial investment is small, the maintenance is high (as we need to reapply changes with every release) and the business value of the code is low. Alternative is to fork the open-source component, which brings us to the problem in the previous paragraph.

We might also decide to contribute or open source internally developed extensions of Open Source library, gaining free QA and possibly bugfixes. We should not open source code that gives us [our product] significant advantage over alternative solutions on the market. We must not share non-generic code, capturing: business processes, algorithms, site-specific logic, etc.

And now is the time for the mandatory list at the end of the post. I'm going to enumerate a few build vs buy decision anti-patterns:

  • Not Invented Here (NIH) Syndrome - you know, when we write your own thing because we are too lazy to do our research or read the docs.
  • The Wrapping Party - every external library is wrapped in order to integrate into the proprietary architectural framework. Though it might look like a good decision, it often leads to difficulties in the debugging, inability to apply best practices and tools, and generally inefficient use of the library
  • Nobody Got Fired for Buying Expensive Stuff - when technical decisions are taken by managers without enough information (or understanding). Sometimes this is rationalized as that all the products look the same on paper, so at least this one comes from a reputable company we can sue. Problem is that often the very expensive do-it-all products require a staff of rocket scientists (or vendor consultants) in order to deliver anything after that.
  • The First One is Free - some vendors try to promote their products as open source, while capturing your data and interfaces in proprietary formats and protocols and then selling services around them. The SOA RAD tools and BPM tools are particularly bad offenders here. The problem is that this limits the ways for evolving your platform. The way to prevent this is to always be aware what part of the solution is platform specific: configuration (is it documented file format), POJO vs proprietary interface components, can you get the whole solution as a bunch of text files, what protocols are used for communication, what is the data storage, can we plug our custom infrastructure, where?

Tuesday, June 3, 2008

The Shape of Complexity

Some things are complex and there's no way around it. Still, even if we can't remove the complexity, often we can shape it into different forms. Some applications have shallow and wide complexity - many simple things with relatively few dependencies, but the overall system has mind-boggling emergent behavior (my favorite 25kloc perl scripts example). Other applications have narrow and deep complexity - small code base, but using so much infrastructure amd metaprogramming, that to understand what's going on, you need to be expert in the platform (think about Hello World written with EJB2 or any application using Ruby on Rails).

The horizontal complexity is pretty easy to deal with - find two similar things and create abstraction for them, rinse and repeat. It is important to stop and look every now and then for similar abstractions and for ugly usages. Eliminate the similar abstractions by extracting common functionality in helpers or superclasses; deal with the ugly usages by splitting the abstraction.

By definition, when we introduce abstractions, our complexity becomes 'narrower' and 'taller'. If we put too much stuff into the abstract classes or we nest them too much, we might transform the bunch of simple classes that we couldn't understand when taken together into a somewhat smaller bunch of more complex classes that we can't understand even in isolation. If go overboard in the other direction, e.g. adding too many facades and convenience methods, the API becomes too big without providing enough benefit to learn it (canonical example - I know a project that has a Strings class, containing constants for empty string, single digits, punctoation marks, single letters and other. Apart from being pointless, more verbose and difficult to apply consistently, this also couples all classes in that project to the util package).

So, how do we end up with code base that is neither too tall, neither too wide, but just the right shape?

  • Acknowledge that the right shape depends on the individual - some people can cope with more abstraction, while others can remember more facts. A metric for abstraction efficiency can be defined as delta-loc/nlevels-of-indirection (where n is a constant bigger than 2).
  • Keep in mind the choice of tools - for example IntelliJ IDEA excels at navigating well-factored code, while Vi people often prefer decoupled classes that can be changed with low risk of impacting other areas of code.
  • Consider the infrastructure maturity - using XA transactions with JMS is simple, debugging buggy JMS (caugh.. activemq.. caugh) is entirely different issue.
  • The experience of the team is important - for some people JMS is the most obvious way to send a piece of data once and only once to another system; others treat JMS as black magic and resort to FTP and cunning rename+move schemes, involving multiple directories and recovery scenarios.
  • And finaly, even if different pieces of infrastructure can provide similar functionality, sometimes they vary by the way they do it - in my previous article about component granularity, I mentioned the fat component vs fat Mule configuration scenarios. In this case, we can move the complexity between the Java code and the Mule code. Mule provides out of the box abstractions for threading, routing and transforming, but it is not great as a general-purpose process definition language. Java provides general purpose language, but does not provide high level primitives for threading and routhing. Another example: consider running OLAP against OLTP schema and dedicated warehouse schema - it works, but the difference in speed and CPU utilization can be orders of magnitude.

About Me: check my blogger profile for details.

About You: you've been tracked by Google Analytics and Google Feed Burner and Statcounter. If you feel this violates your privacy, feel free to disable your JavaScript for this domain.

Creative Commons License This work is licensed under a Creative Commons Attribution 3.0 Unported License.