I am very excited to receive my Google Wave Developer Sandbox account.

Google Wave is actually three layers - the Product, the Protocol, and the Platform. What I am seeing in the Developer Sandbox is actually the Product using the Platform and the Protocol.

After spending a couple of hours with Google Wave product, to say the least, I am amazed at it’s complexity and it’s richness as a comprehensive unconstrained communication platform. If we can conquer it’s complexity perhaps by using a simpler Google Wave Application, I wonder what this would become in a year.

I cannot help but compare Wave with the traditional communication channels. So, here it goes:

Wave vs. Wiki/Microblogging/Email/IM/IRC:

  1. Wave messages live on the Wave server instead of the local client.
  2. A complete history of each Wave as to who did what and when is maintained on the server and it can be replayed any time.
  3. Google Wave is built on the Google Wave Federation Protocol is an extension to the core of XMPP.
  4. Liveness: Editing a wave is immediately visible to other users as it is edited it. You can watch your contact edit a wave live.
  5. Tagging and built-in search available.
  6. The Wave platform supports two types of Wave extensions - Gadgets and Robots. This gives Wave a lot of potential, openness and richness.
  7. Google Wave session is encrypted (https).
  8. Google Wave is actually three layers - the Product, the Protocol, and the Platform.
  9. The actual Google Wave UI seems to be very fast and responsive. But, is still very raw and unstable in a few areas. Some features seem to be disabled right now. This is understandable because the beta product is still possibly a few months away.
  10. Google Wave is a web application and so only a browser is required. 

 

I was warned that IE 8 is not a supported browser. However, after I chose the option to continue, it worked. To be safe, I used Google Chrome 2.0 :)

I plan to read, experiment and blog more about the Google Wave Platform, Protocol and Wave extensions in the near future.

Technorati Tags: , ,

Hibernate and Composite keys

March 22nd, 2009

I like using surrogate keys for most of the database designs for the following reasons:

  1. Simplifies design and may improve efficiency
  2. Maintainability: Change to the meaning of the natural key could change the table structures when using natural keys
  3. Natural key values may be recycled
Having said that, we sometimes are forced to use natural/composite keys when stuck with a legacy database.

Here is a partial list of issues I have encountered when using Hibernate with composite keys on a legacy database:

  1. The documentation (or lack there-of) for Composite Keys usage poses big problems. But, the source code really helps .
  2. Inserts/Updates are slightly inefficient when compared to surrogate keys if there is no versioning strategy implemented.
  3. Cannot have relationships (with CRUD operations) mapped in hibernate for each of the keys in the composite primary key. A read-only collection mapping is possible by mapping the relationship with the same column (that is part of the Composite Key) and making insert=”false” and update=”false”.
  4. It is impossible to determine if the object to be saved is a new one or an existing one when using “assigned” composite keys. Since the keys are “assigned”, the primary key is not null and so it is hard to determine if this is a new object without making another call in a new transaction to the DB. This becomes very cumbersome.
  5. The Hibernate reference documentation uses various phrases like “discourage it for serious applications” for certain types of Composite-id mappings (embedded composite identifier). There are several issues with using key-many-to-one mapping in the Composite-id elements, etc.
  6. In older versions of Hibernate (before 3.3.x), you can’t use an IdentifierGenerator to generate composite keys. The suggested approach was to use UserType or CompsiteUserType. A lot of people choose to use “assigned” strategy to avoid the complications with custom types. I think this is resolved in the latest Hibernate version. Again, the documentation here is almost non-existent. In order to make this work in my code, I had debug through the Hibernate source code and also use the test case code attached in this Hibernate CR.
I am sure there are more, but I cannot remember them now. But, will blog as I remember them.

Technorati Tags: , ,

Mock objects and Testing

March 15th, 2009

This has been a much discussed topic over the web in the last couple of years. I was responding to one of the emails at work about mock objects. While organizing my thoughts about Mock objects, I decided to write this post.

 

Various thought leaders in TDD promote Mock objects. I agree with some of it but not everything they say.

 

Some caution towards using Mocks extensively:

  1. Using Mock objects might affect design decisions:
    • The mocked classes (and the methods used to set up expectations) cannot be final. If called, their normal code may be executed. I prefer making every class either final or abstract unless there is a strong reason to not to do so.
    • A class with only private constructors cannot be instantiated.
    • The behavior for equals() and hashCode() when using mocks may not be what you normally expect.
    • Private methods cannot be mocked. I prefer making every method private unless there is a strong reason to not to do so.
  2. Trustworthiness & ROI of Mocks: Mocks may hide integration problems and push the burden on other tests. High-level and End-to-end tests give the most ROI, in my opinion. I would value these over the unit tests that use mocks extensively when constrained by Time & Resources. Most of the times, I have seen that tests using mocks extensively completely miss the intent of the test..!
  3. Increased complexity and maintenance costs - Setting up mock object expectations create clutter and duplication to test code. Mocking Fine-Grained or Chatty Interfaces results in a lot of brittle unit-test code. High-level tests may not require such extensive changes.
  4. It is a well-known fact that unit tests (that use mocks extensively) don’t catch as many bugs as the integration/high-level tests.

I do not want leave an impression that I do not like the idea of using Mock objects for testing. We just need to use it for the right things and right places after understanding it’s rewards and risks, just like any other tool/framework.

 

Mocking is still suitable for various scenarios that include:

  1. Testing sub-systems that don’t exist yet or are being developed separately. But, then after the dependent code is available, I would switch back to real code from mock objects.
  2. Legacy code that does not have interfaces and is tightly coupled.
  3. Sometimes we may need to mock only some methods of a class and keep the normal behavior of others.
  4. Testing against slow/heavyweight components that have significant dependencies.
  5. To simplify Unit testing when there are no alternative ways to test the same effectively (for example, if the dependent component is very hard to setup/configure, etc.).

IMO, choosing the right scenarios objects (if any) for using Mock objects is the trickiest part.

 

I personally avoid using Mock Objects (unless there are no other easy options) by using good OO Design & Programming practices to write my code such that it is testable without having to use Mock Objects.

Technorati Tags: ,

Last week, during a casual chat with our Agile evangelist, I asked about what could be improved in our team based on what he observed.

He quickly said that it depends on a lot of things and that it is difficult to give feedback without being part of the team. He asked me to pose that question to the team. We already do that in retrospective meetings.

But, after pushing further to get some high-level things that we could improve upon, he gave me a few suggestions:

  • Adopt pair-programming for every line of code that we write.
  • Increase the level of communication between team members
  • Everyone needs to really pay attention during stand-ups
  • Work towards overall team productivity rather than individual productivity
  • …..

My immediate reaction as soon as I heard “pair-programming for every line of code” was to point out that it may not be the right thing to do all the time. Now, I realize how stupid I was..! I was asking for feedback. I should have shut my mouth and should have treated every piece of advice as a compliment. I did thank him for his time, however.

This was very valuable feedback. I need to apologize to him tomorrow for arguing with him even if I did not completely agree with his opinion.. :)

Technorati Tags: ,

The combination of PropertyPlaceholderConfigurer and PropertyOverrideConfigurer classes in Spring Beans API have been invaluable for me to simplify configuration properties for a few of applications I have worked-on recently. The placeholder configurer helps us to share the properties across various pieces of the application using “placeholders”.

As recommended in the Spring reference manual, I usually setup a “default” configuration file (app.properties.default) file that is packaged within one of the main Jar files. This keeps the actual (overriding production) properties file very short as you only override the properties that are different than the default properties file.

Sometimes, a simple loading of the configuration properties may not be enough. There might be a need for post-processing the properties using some custom code.

Certain properties may have to be:

  • Selectively disabled/enabled
  • Translated based on the values of others
  • Set & be available within the application (in the code that is not wired-up in Spring XML)

Spring does have hooks for some of these to decrypt/encrypt properties, intercept the processing of each of the String values, etc. This means writing a new class that overrides the natural behavior of these Configurer classes.

Both of these Configurer classes are implemented as bean factory post-processors. So, if ApplicationContext is used instead of BeanFactory, these should automagically work. If you are using BeanFactory interface (eg., XMLBeanFactory class), then you will need to construct these Configurer classes and call the “postProcessBeanFactory” method by passing the BeanFactory instance as a parameter.

This method is also very helpful if there is a need to centralize the post-processing logic in one place and if this logic involves a lot of custom coding:

public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException

As per the Javadocs, this method is invoked after all bean definitions have been loaded, but no beans have been instantiated yet.

Technorati Tags: , , ,

I designed and implemented a dual-API SDK at my current job. This dual-API SDK did not initially run on any application server.

During this implementation, I learnt that it is best to use a dynamic language like JRuby or JPython or Groovy for demonstrating & learning the capabilities of the API as well as interactively test some edge-case scenarios that are not so easy to automate (randomly causing network outages, database outages, etc.). This was very useful especially at the Sprint reviews to demonstrate the new functionality.

It is incredibly easy it is to set up some complex scenarios interactively using the Java API calls in one of the above 3 dynamic languages. We are still using JDK 5 and so could not take advantage of the built-in scripting support in JDK 6.

We chose to use JRuby (due to the familiarity of Ruby to some developers) even though my favorite was JPython, especially because I have had experience building a large-scale enterprise system using Python in one of my previous jobs at a startup.

However, we ran in to one big problem: The APIs (API interfaces) that use Java Generics were impossible to test using JRuby. We kept the usage of generics to very minimal in our client API interfaces but for obvious reasons our SPI-side interfaces used generics heavily.

After a while, I also realized that it is impossible to type all of the JIRB commands correctly. Any typos in JIRB can lead to really ugly stack traces on the console. Hence, the need for tab-completion and file-based history to remember all of the commands that can be accessed by using the up-arrow/down-arrow keys.

Also, as a nice touch to our Sprint review demos, we customized the command prompt to display our product name (I have changed that to “MYSDK”, below). So, the following .irbrc file was created and copied to the user.home dir.


# ~/.irbrc
# enables Tab completion
require 'irb/completion'

#IRB.conf[:PROMPT_MODE] = :SIMPLE
IRB.conf[:USE_READLINE] = true
IRB.conf[:ECHO] = false
IRB.conf[:IRB_NAME] = “MYSDK”
IRB.conf[:DEBUG_LEVEL] = 0
IRB.conf[:AUTO_INDENT_MODE] = true

# Setup a file-based history across sessions of irb
require ‘irb/ext/save-history’
IRB.conf[:SAVE_HISTORY] = 100
IRB.conf[:HISTORY_FILE] = “#{ENV['IRBRC']}-history”

require ‘java’
import java.lang.System

# SDK stuff
# My SDK imports go here..

Technorati Tags: , , , , ,

OSGi for Web Applications?

January 27th, 2009

Web applications are the most common type of deployments on the application servers.

So, if OSGi is going to be a serious contender in the application server market, I would expect it to have great support for deploying web applications using WAR files. So, I looked through the existing documentation on eclipse.org and played with Equinox, Tomcat and Jetty. Here is what I have learned so far:

There are two ways to integrate Equinox’s implementation of OSGi into your server-side environment:

  1. Embed your web application server within OSGi server
    • Native OSGi HTTP service implementation of Servlet API 2.4
    • Jetty-based implementation - Also requires the usage of the dynamic OSGi HTTP Service.
  2. Embed OSGi server into your existing web application server
    • Equinox Bridge Servlet (Front controller servlet)
    • Dynamic OSGi HTTP Service using the Equinox Bridge Servlet

Option #1 means that the developer is forced to use OSGi HTTP Service. This is great for new web applications built from scratch. The user can programmatically register the servlets and add service listeners to listen for any events (if any one of these instances are started, stopped or updated, we are notified). But, this complicates the development effort required for making an existing WAR file work with this setup. Traditionally, Servlets have been considered “static” - They do not have to be installed/started/stopped dynamically. So, the “dynamic” OSGi HTTP service becomes an overkill in this particular case, IMO. The other disadvantage of this approach is that not all aspects of the Servlet spec are implemented here. For ex., Servlet Filters are not yet available in the native OSGi HTTP service implementation. I am not sure how clustering can be achieved here.

Option #2 uses the standard “Front-controller” pattern and uses the Bridge Servlet as a Front controller servlet. org.eclipse.equinox.servletbridge and the Servlet API are exported automatically to the underlying OSGi framework. So, the modules deployed in the OSGi server have access to the Servlet API to register/unregister servlets. This approach obviously uses the web.xml. So, you can add more servlet mappings for JSPs, if necessary. The other sub-options here revolves around using this Servlet bridge to provide the dynamic OSGi HTTP service.

So, I do not feel comfortable with both of the above options provided by Equinox OSGi implementations. Perhaps, other implementations might have better solutions.

No wonder the folks at SpringSource chose not to implement OSGi HTTP service in their SpringDM server platform for now. They support the standard WAR file deployment within their embedded Tomcat server. This seems like a pragmatic approach to me to support all the existing standard Web Application Archive (WAR) files.

Although I like the other dynamic services (Logging, Configuration, Event Admin Service, etc.) in the OSGi Service Compendium, I am not so sure about the HTTP Service, especially for existing web applications.

What do you think?

Technorati Tags: , , , , ,

Stig’s identity revealed..!

January 21st, 2009

TopGear is one my favorite TV shows. One of the attractions about TopGear was the suspense about the Stig, especially after the hilarious introductions (”some say…..”) of the Stig by Jeremy Clarkson in almost every show.

Today, this was revealed by BBC. The facts are even more shocking. I just cannot believe it..! He is 80+ yrs old Graham Hill, who won the GP World Drivers Championship in 1962 and 1968 and was reported to have died in a crash back in the 70’s..!

TopGear rocks..!

Here are some more reasons why I love them so much:

  • In-depth knowledge & expertise, great reviews of automobiles
  • Humorous and Witty
  • Camaraderie among the presenters and stereotyped characters (”Captain slow”, “Hamster”, etc..)
  • Hillarious & Insane ideas and Challenges involving automobiles

I guess TopGear could not hold back Stig’s identity after all the crazy speculation amongst the viewers.

Technorati Tags: , ,

I am a big fan of the Hibernate’s direct field access functionality. I am not sure why ”property” access is the default instead of “field”. Direct field access allows me to control the number of getters/setters that are actually needed from the DAO Client’s perspective.

I think using property access helps enforce better encapsulation of the data in the mapped/persistent classes. I have seen that most developers just use public getters and setters for all of the properties in the mapped class.

This creates problems for collections, especially. I seldom expose getters and setters for collections. I always use a combination of “addXXX(Obj)”, “removeXXX(Obj)” and “clearXXX()” (depending upon the need) instead of “get/setXXX”. This is for efficiency (as Hibernate uses a custom collection class) and better encapsulation.

The only situations where I do not use the direct field access are:

  • If the DB schema data type does not directly map to the mapped attribute in Java where a translation is required. This is mostly true for Legacy Database schemas and also where custom introducing custom SQL type mapping is not an option perhaps due to inconsistent use of the same data type in legacy applications.
  • If there are dependent (child) tables that have composite primary keys (which include the primary key of the parent table). In this case, for saving a new entity I would need to intercept the setter of the primary key of the parent table to set the appropriate fields in the child tables.
  • If I use lazy initialization, I would use property access for the primary key. This allows us to call persistentObj.getId() without completely initializing the proxy. This is applicable only for the “Id” field.
  • If there is any other need to intercept the getters/setters for whatever reasons (validation, logging, debugging, etc.). This is very unlikely.

Technorati Tags: , ,

Agility and large Backlogs

January 11th, 2009

Backlog is used for prioritizing, tracking and communicating the work (work items) to be done in the future Iterations/Sprints.

There may be multiple teams working from one backlog, but if there are more than 3-5 sprints worth of work items for all teams working on that backlog, then I consider that to be huge. I have noticed that if the product owner is not careful, the backlog can grow and become really huge.

This is not good for several reasons:

  • It is depressing for the everyone on the team. This may lead to a belief among team members that this is a case of a large product with not enough resources.
  • Priorities change - It is a waste of effort for the product owners to endlessly sort through the work items in the backlog every Sprint to come up with a list of stories for a Sprint.
  • Some of the items in the backlog are never worked upon even after months/years. In that case why spend effort prioritizing them?
  • It is hard to react to change in the market conditions, when the teams are so focussed on possibly “stale” requirements in a backlog.

So, what are the possible causes for this?

  1. Lack of clarity of product vision.
  2. Disagreements between the product management and marketing about the importance of features. So, the “unimportant” ones (mostly due to disagreements) find the bottom of the backlog.
  3. Product owners unable to decide on the “business value” and ROI on requirements in the backlog. This may be due to the lack of authority (to do so) or communication breakdown or just the organization culture itself.
  4. Sometimes, for various reasons, a suite of products might have one product owner per product who do not necessarily agree on everything especially when it comes to the cross-product requirements.
  5. Inadequate resources, unstable team, attritions, shuffled team members, not-so-well-performing teams, etc.
  6. Treating defects as backlog items. Sometimes, a lot of medium defects are tossed in to the backlog.
  7. Poor/Complex Technical Architecture - This means that the features get done much slower than estimated.

Technorati Tags: , , ,

TOP