Archive for the ‘Development’ Category

Dear Eclipse

It’s over, we’re done. No need to come by and collect your stuff. Your workspace is already in the trash. There’s no trace you were even here.

I still remember when I first gave you a shot. I had tried other IDE’s, but all they seemed to offer where headaches. Vim and Ant simply worked better.

But then you came along, with compile as you type and amazing CVS integration. Suddenly, my collection of a half dozen command line utilities were reduced to one. I was so taken with SWT and it’s ability to look native on each platform, that I even wrote an entire application in it.

My love only grew when I took a professional development job. I had to use Windows, you made it possible to get something done. But looking back, that’s also when our relationship started to crack. We switched from CVS to SVN, negating one of the greatest advantages you had.

I switched jobs again and this time I was introduced to Intellij IDEA. Sure it was nice, but it didn’t compare to you. It’s version control integration was confusing. It didn’t support all features and languages you did, and it’s auto-compile just didn’t work as nicely. I stuck with you.

But the cracks that appeared earlier started growing. Each new feature you supported and every new plugin written for you never seemed to work right. Everything had rough edges, caveats, and felt distinct from everything else in the system.

You just didn’t take care of yourself. As computers got faster, you got slower. Every editor seems slow to respond to keyboard input. The XML editor is the single worst editor I have ever used. Typing in your IDE shouldn’t feel like telneting over a dial-up connection. You started bloating up to the size of a beached whale in a sad attempt to be everything to everyone. While you allowed everyone to attach to you, you forgot about what made you great in the first place, Java development.

You didn’t keep up with the best practices. You don’t work well with maven projects. Refactoring doesn’t work across the entire workspace. You should never ask me for the location of the source for a class when it is in your workspace. It’s 2010, these are things you should do right by now.

One of your great features was the ability to use external editors for resources managed by the IDE. Unfortunately, whether or not that file was refreshed in the workspace seemed like a decision that rested in God’s hands.

Lets not even talk about version control. The subclipse/subversive split was a disaster and your git support is a joke. You once replaced my entire stack of tools. Now to get anything done, I now have to open a bunch of terminals, gitx, textmate, and you.

Remember that other IDE I played around with? It’s kept itself in shape. It looks better than it ever has. It never promised to do everything, and that’s left it with few wrinkles and sharp edges. It works with a Maven project structure, has real support for Git, and does a fantastic job of editing Java. And now it’s open source too, just like you.

That’s why it’s over. It’s always sad to see something with so much promise ruined by neglect and bloat. But it is what it is and it’s time to move on.

  • Share/Bookmark

Are you there to ship, or write code?

Amro Mousa tweeted about a great post by Joel Spolsky about Duct Tape Programmers. Also known as hackers, rockstars, and problem-solvers duct tape programmers are the ones that just get it done.

The line that resonated the most with me is the following quote from Jamie Zawinski:

But that’s not the point—you’re not here to write code; you’re here to ship products.

Unfortunately, I don’t think this is always true. In many organizations, especially the larger, more layered organization, the responsibilities of developing the software and shipping it are held by two different stake holders. The job is to write code, nothing more, nothing less.

This can be the most infuriating and frustrating environment for a duct tape programmer. The metrics are all wrong. Number of test-cases, tickets closed, features on the box, length of scrums, etc, don’t matter if nobody is using the product.

Thankfully, if you think your responsibility is really to make things that get used, there are some early signs that a position might or might not be a fit:

Things that should make you worry:

  • Being asked for a BrainBench certification
  • A 30-minute interview of nothing but syntax questions
  • Lots of questions about keywords
  • Greater emphasis on process than the problem
  • Constant quizzing on the technology mentioned in your resume

Things that should make you feel good:

  • The interviewer describes the problem and how they’ve solve some of it
  • You describe some of the problems you’ve faced and how you’ve solved them
  • You and the interviewer start brainstorming how you’d start solving the rest of the problem
  • You and the interviewer realize that you’re both way over time and are missing something important

The first set of questions determine how well or quickly the candidate can produce code, but there’s nothing in there that explores whether any of that code ever did anything useful. The product is the vehicle, the code is the driver.

The second set is for the duct tape programmer. The code might not have been the most idiomatic or the best covered, but this person has written code to solve the problem in the past and is already thinking about how solve the next ones. In this case, the code is the vehicle that’s driven by the product.

Using these these lists as guidelines can help you find the right fit and place where you can be the most productive, while avoiding misery and a padded cell. Is there anything missing from the lists?

  • Share/Bookmark

Standalone Rails Migrations

One of the most annoying things about deployments are dealing with databases. In the Java world, using Hibernate to generate your schema is pretty common. It works well in development, where you generally re-create and re-seed your database after each model change. However, it can be disastrous when deploying. It felt like each sprint needed a dedicated day for diff-ing the database schemas and figuring out what changed and what needed to be applied. Often, indexes would be forgotten, resulting in un-foreseen slowness.

Ruby on Rails solves that problem with using migrations. Migrations describe how to move from one version of the database to the next. While it’s built into Rails, I came across Standalone-migrations on GitHub. Not surprisingly, it exposes the core functionality of Ruby on Rails migrations, allowing you to embed it in any kind of project. You’ll still need Ruby to run the migrations along with the correct gems for connecting to the database.

Of course, Ruby on Rails migrations have a few downsides. Personally, I believe that the database should be aware of constraints and relationships. This has other practical benefits, such as automatic indexes. By default, Rails Migrations do not support foreign key’s natively. Simon Harris wrote a plugin to automatically associate foreign keys. Way easier than writing SQL.

Getting a rails plugin to work standalone required some munging, so I ham-fisted Standalone Migrations and Foreign Key Migrations together and put the project on GitHub. If this is something you need, clone my fork of Standalone Migrations.

  • Share/Bookmark

Migrating TestTrack to JIRA

In another long fought battle that eventually led to victory, we finally moved off TestTrack to JIRA Studio. Of course, now I got stuck with the task of figuring out how to get the open defects from one system to the other. Thankfully this ended up being somewhat un-painful. The Jira4R gem allows for easy creation of issues with just a few lines of Ruby. There are a few caveats to using this script. The documentation is almost non-existent and very out of date. It’s also not available on any standard gem repository.

In order to save another fellow developer the headaches I went through, I’ve published the source for my migration script on GitHub. It includes examples of how to use the Jira4r gem as well as installation instructions. Feel free to fork away and make it better!

  • Share/Bookmark

Customizing Spring Security with Legacy Transactions and Authorization

A few months ago at work I got stuck with a rather daunting assignment: to make Spring Security work alongside our legacy security model.

The rationale was sound. We have a legacy UI and we want a smooth transition to the new one. Which means that as much of their information, including their credentials need to carry over. Furthermore, our application runs load-balanced in the production environment and we can’t make use of sticky sessions. Which means that the solution needs to integrate with our database-backed sessions. If that was not complicated enough, there was also a lot of hidden authorization code that relied on specific properties being set in ThreadLocal.

After a few months of trial and error, I think I finally have a solution that both works and doesn’t lock the database. There are quite a few steps and the process is somewhat lengthy. For that reason, the rest of this tutorial is under the fold.
Read more

  • Share/Bookmark

Integration testing Spring MVC Annotated Controllers

Annotations and POJO controllers make dead simple to unit test the web layer and ensure that the logic within it is correct. What’s not as clear is how to quickly (and automatically) test the configurations of your controllers and ensure the correct controller method is called with the correct parameters on a request.

After looking through the Spring MVC tests, it becomes apparent that you want to create a DispatcherServlet and send it requests. If the DispatcherServlet is initialized with the correct context, it will then behave just as it does in your web container. It will look at the request, find the correct handler, and make the appropriate controller call. I created three classes to help set up the environment.

public class MockWebContextLoader extends AbstractContextLoader {
 
    public static final ServletContext SERVLET_CONTEXT = new MockServletContext("/WebContent", new FileSystemResourceLoader());
 
    private final static GenericWebApplicationContext webContext = new GenericWebApplicationContext();
 
    protected BeanDefinitionReader createBeanDefinitionReader(final GenericApplicationContext context) {
        return new XmlBeanDefinitionReader(context);
    }
 
    public final ConfigurableApplicationContext loadContext(final String... locations) throws Exception {
 
        SERVLET_CONTEXT.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, webContext);
        webContext.setServletContext(SERVLET_CONTEXT);
        createBeanDefinitionReader(webContext).loadBeanDefinitions(locations);
        AnnotationConfigUtils.registerAnnotationConfigProcessors(webContext);
        webContext.refresh();
        webContext.registerShutdownHook();
        return webContext;
    }
 
    public static WebApplicationContext getInstance() {
        return webContext;
    }
 
    protected String getResourceSuffix() {
        return "-context.xml";
    }
 
}

The MockWebContextLoader loads in the spring config locations and creates a WebContext . In order for this environment to mimic the one in your web container, you will need to pass in the same configs. I will show you how to do that later.

To help validate the success of a test, I’ve created another ViewResolver that just echoes the viewname into the response. You could have the ViewResolver return the correct view, but parsing that to gauge success seemed like too much of a headache.

public class TestViewResolver implements ViewResolver {
 
    public View resolveViewName(final String viewName, Locale locale) throws Exception {
        return new View() {
            public String getContentType() {
                return null;
            }
            @SuppressWarnings({"unchecked"})
            public void render(Map model, HttpServletRequest request, HttpServletResponse response) throws Exception {
                response.getWriter().write(viewName);
            }
        };
    }
 
}

Finally, I created an abstract class that would handle the creation of the DispatcherServlet for all tests that extend it. I’ve put my spring configuration files on the classpath that my test run it. If your configs are elsewhere, you will need to modify MockWebContextLoader to look in a different path.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader=MockWebContextLoader.class, locations={"/classes/spring.xml", "/springmvc-servlet.xml"})
public abstract class AbstractControllerTestSupport {
 
    private static DispatcherServlet dispatcherServlet;
 
 
    @SuppressWarnings("serial")
    public static DispatcherServlet getServletInstance() {
        try {
            if(null == dispatcherServlet) {
                dispatcherServlet = new DispatcherServlet() {
                    protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
                        GenericWebApplicationContext wac = new GenericWebApplicationContext();
                        wac.setParent(MockWebContextLoader.getInstance());
                        wac.registerBeanDefinition("viewResolver", new RootBeanDefinition(TestViewResolver.class));
                        wac.refresh();
                        return wac;
                    }
                };
 
                dispatcherServlet.init(new MockServletConfig());
            }
        } catch(Throwable t) {
            Assert.fail("Unable to create a dispatcher servlet: " + t.getMessage());
        }
        return dispatcherServlet;
    }
 
    protected MockHttpServletRequest mockRequest(String method, String uri, Map<string ,String> params) {
        MockHttpServletRequest req = new MockHttpServletRequest(method, uri);
        for(String key : params.keySet()) {
            req.addParameter(key, params.get(key));
        }
        return req;
    }
 
    protected MockHttpServletResponse mockResponse() {
        return new MockHttpServletResponse();
    }
}
</string>

With this harness, it’s trivial to automatically check the configuration of the web controllers. Since the functionality is tested separately from the configuration, the problems can be isolated quicker, leaving more time to fix them.

  • Share/Bookmark

Reasons for using the GIT SVN bridge

I’ve already posted about why I like Git better than Subversion. This motivated me to install the GIT-SVN bridge up to my work SVN repository.

Using the bridge is a bit confusing at first. This tweet by Calvin Yu pointed out is right on the money. Git’s interface isn’t great, but it is powerful. There are two major resources that I use to use the bridge effectively: this blog post and the git-svn man page which has a lot of examples. Between the two, I’ve been able to do almost everything I want.

So why go through the effort of cloning your SVN repository (which took a half day for me)? What follows are my reasons.

Local Branching

We’ve got a fairly large development team. If we let encourage every developer to create a branch for each whim, our branch space would be quickly polluted. Since most of the exploratory work is generally done by one person, there isn’t any real need for collaboration either. The end result is work that often just disappears as developers find it hard to maintain a lot of uncommitted changes.

Git allows you to create local branches. These branches exist within your repository. You can commit to them as often as you like.

Fast Branch Switching

Git is a clone of your whole repository. Most importantly, it’s an efficient clone of the whole repository. Which means you only have to download deltas when you change branches. If you need to work on a new branch in SVN, you need to check the whole thing out. On a sizable repository hosted off-site, this can take a while.

Recently, I was working on a local branch. I needed something from the head of another branch, so I checked that out and did what I needed to do. Then I got an email from my boss asking me to look at a bug. I checked out trunk. It was an easy fix and shortly thereafter, I got another email asking me to commit it to the release branch, a branch that I’ve never checked out. I checked it out and committed it there too. With git-svn, this whole process took 20 minutes, including the time to fix the bug. Given that each branch is nearly half a gig, and our outside line isn’t very fast, that’s pretty impressive.

Cherry Pick

Git has a command that pulls a single commit from one branch to any other branch. Sure you can do the same thing with SVN merge, but nobody remembers that syntax.

Local Commits

It’s really nice to be able to occasionally commit intermediary code without breaking the build. When I make a mistake or can’t figure out why something that was working isn’t anymore, having past versions to look at is helpful.

The Stash

Occasionally you have to switch gears. Git Stash lets you do that without losing work.

Being Trendy

Hey, style is important too :) Seriously, the benefits outlined above, though simple, can save a massive amount of time when things are breaking all over the place. That alone is causing the use of the bridge to slowly spread through the organization.

  • Share/Bookmark

Chaining Mootools Events Explained

There’s tons of doc out there explaining how to chain Mootools events, but very little of it really explains what’s really going on, why the code looks the way it does, and most importantly, how to get it to do what you want. This is my attempt to fill in the gap with Mootools 1.2.1.

Chaining

The basic problem is that the way people do transitions in javascript. Every transition library effectively just does something very fancy around setTimeout. This works well if you’re just sliding in an element, but if you want to slide out an element, then slide in another one, you get something that looks very weird, if you’re not careful. Transitions aren’t atomic functions. When the javascript interpreter hits a setTimeout in Transition A, it moves on to Transition B, and vice versa. Effectively they happen at the same time.

To get what you want, Mootools includes the Chain class. From the doc:

A Utility Class which executes functions one after another, with each function firing after completion of the previous. Its methods can be implemented with Class:implement into any Class, and it is currently implemented in Fx and Request. In Fx, for example, it is used to create custom, complex animations.

Chain is implemented by the Fx.Tween class. The Fx.Tween class is the class that allows you to transition between various style properties. This super simple example shows how to switch between background colors for the element with id="example1"(download mootools_chaining):

    var fx = new Fx.Tween($('example1'));
    fx.start('backgroundColor', 'red').chain(function() {
        this.start('backgroundColor', 'blue')
    }).chain(function() {
        this.start('backgroundColor', 'green')
    });

All I’m doing here is creating a tween on the element example1. Then I turn the background red, blue, and green (in that order).

Ok, that looks easy enough. But what if I want to do something more complex, such as fade out one element (example2_header1), and fade in another (example2_header2)? The first thought would be to do something like:

    // THE WRONG WAY TO DO IT!
    var fx = new Fx.Tween($('example2_header1'));
    fx.start('opacity', 0).chain(function() {
        this.set('display', 'none');
    }).chain(function() {
        $('example2_header2').setStyle('display', 'block');
    }).chain(function() {
        $('example2_header2').tween('opacity', 1);
    });

This example will never show the element example2_header2. To understand why this is, we need to look at the difference between the Fx.Tween.set and Fx.Tween.start methods.

Fx.Tween.set

set: function(property, now){
	if (arguments.length == 1){
		now = property;
		property = this.property || this.options.property;
	}
	this.render(this.element, property, now, this.options.unit);
	return this;
}

Fx.Tween.start

start: function(property, from, to){
	if (!this.check(arguments.callee, property, from, to)) return this;
	var args = Array.flatten(arguments);
	this.property = this.options.property || args.shift();
	var parsed = this.prepare(this.element, this.property, args);
	return this.parent(parsed.from, parsed.to);
}

Notice the difference in return. Fx.Tween.start calls into the Fx parent class, but Fx.Tween.set does not. The Fx.start method creates a timer, and when that completes, it calls the Fx.onComplete method:

onComplete: function(){
	this.fireEvent('complete', this.subject);
	if (!this.callChain()) this.fireEvent('chainComplete', this.subject);
},

Aha! This is why the second example fails. For non-fx type function calls, this.callChain() must be called manually. Thus, the code to get it all working is:

    var fx = new Fx.Tween($('example2_header1'));
        fx.start('opacity', 0).chain(function() {
            this.set('display', 'none');
            this.callChain();
        }).chain(function() {
            $('example2_header2').setStyle('display', 'block');
            this.callChain();
        }).chain(function() {
            $('example2_header2').tween('opacity', 1);
        });
    });

You can download the full working example (including the HTML around it).

  • Share/Bookmark
Return top

About

This is my blog about programming. For random stuff, checkout my Twitter or Tumblr