Sunday, February 12, 2012

Javascript closure with iteration

This is something with Javascript that tripped me up recently:

I had a geographical US map, with the different states highlighted - I used a jquery plugin called maphilight to get the highlights working, and needed to respond to the click event on the southern US states, I had a code along these lines:
var south=["VA", "WV", "KY", "TN", "NC", "SC", "GA", "AL", "MS", "FL", "LA", "AR"];
            for (var i=0;i<south.length;i++){
                $("[title=" + south[i] + "]").click(function(){
                    alert(south[i] + " clicked");
                });
            }


This however does not work - if I click on any of the southern states, the result is actually "undefined clicked".

The reason for this behavior is the closure defined as the click handler - it has a reference to variable "i" and NOT it's value at the point of defining the function, and is resolved only at the point of calling it, which is as a response to the click event. Since it is defined within a loop, i's value at the end of the loop is 12 at the end of the loop, and is resolved as south[12] in the function, and a southern state at this index does not exist

The fix is interesting, I got it from the book - Secrets of the Javascript Ninja and is to use something called an immediate function which looks something like this:
(function(){
.....
})()

Using the immediate function, the fixed code looks like this:
var south=["VA", "WV", "KY", "TN", "NC", "SC", "GA", "AL", "MS", "FL", "LA", "AR"];
            for (var i=0;i<south.length;i++){
                (function(index){
                    $("[title=" + south[index] + "]").click(function(){
                        alert(south[index] + " clicked");
                    });
                 })(i);            

Wednesday, February 1, 2012

Spring MVC 3.1 - HandlerMethod

Spring MVC 3.1 has newly introduced the concept of a HandlerMethod. HandlerMethod is a wrapper around the method which is invoked for a user web request.

For a controller with this signature,

@Controller
@RequestMapping("/accounts")
public class AccountController {

....
 @RequestMapping(method = RequestMethod.GET)
 public String list(Model model) {
  model.addAttribute("accounts", this.accountManager.getAccounts());
  return "accounts/list";
 }

 @RequestMapping(value="/new", method = RequestMethod.GET)
 public String newForm(Model model) {
  model.addAttribute(new Account());
  return "accounts/new";
 }



a HandlerMethods map will be generated mappping the contents of the RequestMapping annotation of the method, to the HandlerMethod, something which looks like this:

path pattern: /accounts method: GET -> AccountController: list(Model)
path pattern: /accounts/new method: GET -> AccountController: newForm(Model)

Now on a user request for say for a GET on /accounts/new the appropriate HandlerMethod is retrieved from the map, and the request dispatched to the HandlerMethod.

Some of the abstractions that come into play are:
1. RequestMappingHandlerMapping - manages the map of path patterns to HandlerMethod
2. RequestMappingHandlerAdapter -  takes in a user request, transforms the request parameters into a state that is consumable by the HandlerMethod, calls the interceptors, and finally invokes the HandlerMethod


The HandlerMethod abstraction has been introduced with Spring 3.1, prior to Spring 3.1, the Handler used to be the controller class itself - when a call from a user comes in, the pattern of the request resolves upto the Controller and then a different pattern matching was performed at the level of the controller by iterating over the  Controller methods to find the right method to invoke. HandlerMethod simplifies the flow significantly by recognizing that a request mapped method is the actual handler and not the controller itself ( this is functional in a way - by making the Controller method a first class citizen).

This change from 3.0.x to 3.1.0 is significant, what I have truly appreciated about the Spring codebase is that this change is transparent to the developers - as long as the Spring MVC defaults are adhered to (using mvc:annotation-driven etc), this change of engine under the covers, just works.

Wednesday, January 25, 2012

NoSQL at IndyJug

I attended a session on NoSQL databases at IndyJUG today. Tom Hunter, the presenter, had done a very extensive research last year on the entire NoSQL landscape for his personal project, and the presentation was a aggregation of this information - he managed to give a good overview of the different NoSQL databases and had a very interesting way of classifying them, if I remember correctly:
1. Column type databases - Hadoop, Big Table
2. Key/Value type - Memcache,..
3. Document type - MongoDB, Couch DB
4. Graph type - Neo4J

Tuesday, January 24, 2012

(-14)%3 and 14%(-3)

Never really thought about it before, if I offhand look at -14%3 and 14%-3, I would have guessed the result to be the same in both cases...but it is -2 in the first case and 2 in the second case.

the rule is a = (a/b)*b + a%b,
(-14) = (-4)*( 3) + (-14)%3
( 14) = (-4)*(-3) + ( 14)%3

Sunday, January 22, 2012

New way of looking at VIM

I am a long time VIM user, but never thought of it this way - http://yanpritzker.com/2011/12/16/learn-to-speak-vim-verbs-nouns-and-modifiers/

Highly recommended if you are planning to take a second look at vim.

Sunday, January 15, 2012

Spring Custom Property Editor - Convert String to Calendar

Continuing on a previous entry:

The previous blog entry was about a custom property editor to convert a string representation of a date to a java.util.Date field. The approach here is a little different, to convert a string representation to a "java.util.Calendar" type, which is a little more complicated.

Say if I have a bean defined this way:

<bean name="project1" class="org.bk.simplygtd.domain.GtdProject" p:name="project1" p:startDate="2010-01-01T12:00:00.000-0800" p:completedDate="2010-01-04T12:08:56.235-0800" p:isDone="true" />


and the class has startDate and completedDate of type java.util.Calendar type.

If no custom property editors are registered this error will be returned when trying to start up the container:

Cannot convert value of type [java.lang.String] to required type [java.util.Calendar] for property 'completedDate': no matching editors or conversion strategy found

This is perfectly reasonable as the container does not know how to transform the Calendar string to Calendar type.

The approach that has best worked for me is to actually write a custom property editor and register it with the container.

This is how my property editor looks:

import java.beans.PropertyEditorSupport;
import java.util.Calendar;

import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.ISODateTimeFormat;
import org.springframework.util.StringUtils;

public class CustomCalendarEditor extends PropertyEditorSupport {
    private final DateTimeFormatter dateTimeFormatter = ISODateTimeFormat.dateTime();

    @Override
    public String getAsText() {
        Calendar value = (Calendar) getValue();
        DateTime dateTime = new DateTime(value);
        return (value != null ? dateTime.toString(this.dateTimeFormatter) : "");
    }

    @Override
    public void setAsText(String text) throws IllegalArgumentException {
        if (!StringUtils.hasText(text)) {
            setValue(null);
        } else {
            DateTime dateTime = this.dateTimeFormatter.parseDateTime(text);
            setValue(dateTime.toGregorianCalendar());
        }
    }
}

Note that I have used joda time as bridge between the string representation and java.util.Calendar and have assumed a ISO-8601 format for date.

Now, to register this property editor:
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
        <property name="customEditors">
            <map>
                <entry key="java.util.Calendar">
                    <bean class="org.bk.simplygtd.spring.CustomCalendarEditor"/>
                </entry>
            </map>
        </property>
    </bean>

That's it, now the conversion between string to Calendar and back should work.

Thursday, January 12, 2012

Spring integration and version 2.0 schema files

Something to note when upgrading Spring Integration from version 2.0 to 2.1.0 -

Schema location to the custom namespace used to be specified this way:
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:int="http://www.springframework.org/schema/integration"
 xsi:schemaLocation="http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.0.xsd

This either has to be explicitly the 2.1 version schema or version less, otherwise the start-up of the container aborts:
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:int="http://www.springframework.org/schema/integration"
 xsi:schemaLocation="http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.1.xsd

More details here: https://github.com/SpringSource/spring-integration/wiki/Spring-Integration-2.0-to-2.1-Migration-Guide