2012-03-22

Refactoring and the Visitor pattern 2. (Spring)

After showing how to decouple subtypes indirectly coupled to a base type via the Visitor pattern in the first part of this writing I demonstrate something more sophisticated.

In the same system another usage of the Visitor pattern impeded the refactoring: In the last of a chain of six singleton Spring collaborators a visitor has been used to accomplish a certain task by visiting the current instance of the blackboard subtype which has been presented in the previous post.
public class CollaboratorUsingVisitor {
  ...
  public void useVisitor(BlackBoardBaseType blackBoard) {
    ...
    TaskAccomplishingVisitor visitor = new TaskAccomplishingVisitor();
    blackBoard.accept(visitor);
    Result result = visitor.getResult();
    ...
  }
  ...
}

public class TaskAccomplishingVisitor implements BlackBoardVisitor {

  private Result result;

  public void visit(BlackBoardSubType1 blackBoardSubType) { ... }
  ...
  public void visit(BlackBoardSubTypeN blackBoardSubType) { ... }

  public Result getResult() { return result; }

}
It can be seen that on every call of the method useVisitor() a new instance of the visitor is created. Since I needed to extract the whole collaborator chain, too, I needed to abstract this visitor from the blackboard subtypes as well. But in order to achieve this a special case collaboration had to be implemented: Singleton collaborator using prototype visitor. It is not very widespread, at least according to the systems which I've seen so far, but definitely a clean solution, because Spring supports lookup-method injection since version 1.x.
There was an additional step to get in a state where the this kind of injection could be applied: Extract an interface specifying the method returning the computed result.
After finishing the refactoring this is how the Java code looked like:

public abstract class CollaboratorUsingVisitor {
  ...
  public void useVisitor(BlackBoardBaseType blackBoard) {
    ...
    TaskAccomplishingVisitor visitor = createVisitor();
    blackBoard.accept(visitor);
    Result result = visitor.getResult();
    ...
  }

  public abstract TaskAccomplishingVisitor createVisitor();
  ...
}

public class ExistingTaskAccomplishingVisitor implements BlackBoardVisitor, TaskAccomplishingVisitor {

  private Result result;

  public void visit(BlackBoardSubType1 blackBoardSubType) { ... }
  ...
  public void visit(BlackBoardSubTypeN blackBoardSubType) { ... }

  public Result getResult() { return result; }
}

public class NewTaskAccomplishingVisitor implements TaskAccomplishingVisitor {
  public Result getResult() { return new Result(); }
}
And this is a snippet of the Spring XML configuration holding the bean definitions for the old and the new module:













In case of the new visitor in the new module there were no requirements regarding what result to deliver, therefore if was completely sufficient to return just a dummy result. With this whole change the collaborator chain could be abstracted and duplicated without having to extract the blackboard subtypes.

2012-03-21

Refactoring and the Visitor pattern 1.

I like the Visitor pattern as one tool for embracing the Open-Closed Principle.
In one of my clients' project I faced two situations where it almost prevented refactoring and since I think the two cases are interesting and important enough I'll demonstrate them in two blog posts.

My roles in the project were development lead, architect and coach and with these responsibilities I tried to improve both, the system's structure and architecture as much as possible. One structural issue was that all subtypes of a generic and central abstract type implementing the blackboard architectural pattern were put in the same module. This lead to a confusing and complicated hierarchy consisting of more than 100 packages and more than 1.000 classes.
I didn't want to let that module grow further for obvious reasons, so I decided to create two new modules: One for the new subtype and another one for components and classes commonly used by the old and the new module. This is why I have extracted the blackboard base type into the commons module and had to deal with the Visitor pattern.
The code was similar to the following:
public abstract class BlackBoardBaseType {
  ...
  public abstract void accept(BlackBoardVisitor visitor);
}

public interface BlackBoardVisitor {

  visit(BlackBoardSubType1 blackBoardSubType);
  ...
  visit(BlackBoardSubTypeN blackBoardSubType);
}

public class BlackBoardSubType1 extends BlackBoardBaseType {
  ...
  public void accept(BlackBoardVisitor visitor) {
    visitor.visit(this);
  }
}

public class BlackBoardSubTypeN extends BlackBoardBaseType {
  ...
  public void accept(BlackBoardVisitor visitor) {
    visitor.visit(this);
  }
}

So if I just would have taken the base type without modification, then I should have extracted all its subtypes, too, because of the visitor. Therefore an extra step was necessary, namely the abstraction of the visitor from the concrete subtypes, what I have solved by introducing an empty (in other uses marker) interface.
public abstract class BlackBoardBaseType {
  ...
  public abstract void accept(EmptyBlackBoardVisitor visitor);
}

public interface EmptyBlackBoardVisitor {
}

public interface BlackBoardVisitor extends EmptyBlackBoardVisitor {

  visit(BlackBoardSubType1 blackBoardSubType);
  ...
  visit(BlackBoardSubTypeN blackBoardSubType);
}

public class BlackBoardSubType1 extends BlackBoardBaseType {
  ...
  public void accept(EmptyBlackBoardVisitor visitor) {
    visitor.visit(this);
  }
}

public class BlackBoardSubTypeN extends BlackBoardBaseType {
  ...
  public void accept(EmptyBlackBoardVisitor visitor) {
    visitor.visit(this);
  }
}

By doing so there was no indirect dependency of the base type on the sub types via the visitor anymore and I could extract it and also implement the new subtype.

2012-03-05

Disable overriding of Spring beans in web applications

I came across this issue when I was working on a client's project which utilizes Spring for wiring dependencies. A new module in the project used the same web services as another one, so it was pretty easy for my junior co-workers to assign already used component names, thus introducing system-wide heavy failures.Although the usage of prefixes theoretically solves the issue, in practice there is no protection for overriding beans if you use a Spring container with the default setting.
Changing such settings is no problem in applications where you have the control of instantiating the container, but it is cumbersome in case of web applications using Spring's ContextLoaderListener for booting the container. Namely, this ServletContextListener takes care of the creation of the appropriate ContextLoader, which in turn constructs the ConfigurableWebApplicationContext whose properties can be adjusted.
So the following steps are required to disable bean definition overriding in a web app:
It would be much better and natural to support a servlet context parameter (such as contextConfigLocation) for setting this essential behavior. 

2012-01-27

JRebel for free and a bug

I've been using JRebel at a client's site for several months by now and I'm very pleased with it. So I decided to use it for my private projects, too. The prices aren't that high, but then I discovered, that ZeroTurnaround offers it just for the price of one tweet or wall message per month. I think this is a great opportunity for them to gain customers by letting them enjoying the advantages of the tool at no charge for an unlimited period of time. Check it out at https://social.jrebel.com/ .

The reason for my increased interest was the following bug which I discovered yesterday and wanted the developers to know that it exists, so I posted a message in their forum with the following description:


The following scenario caused JRebel and thus also the container to hang:

Project structure:
master
|_ module1 - contains Mapping.hbm.xml
|_ module2 - also contains a Mapping.hbm.xml


Renaming one of the mapping files solved the issue, whose cause was very hard to find.
Multiple identical Spring configuration file names are in contrast no problem.


Build system: Maven 3
Container: JBoss 4.2.3
JRebel version: 4.5.4
Hibernate version: 3.3
Java version: 1.6.29
OS: Windows 7

I'm curious, whether and when they react and how they will handle the issue.

UPDATE: Just only a few hours after this post has been submitted it got comments from two developers of ZeroTurnaround - this is what I call excellent service!

Searching for Software Craftsmen

You're a Clean Coder.
You're involved in open source projects.
Software development is not only your profession, but it's also your mission.
You want to create sophisticated Java enterprise systems in a team with other experienced software craftsmen.
You're tired of working with so-called developers, who don't even know the difference between unit and integration tests.
You love being on the bleeding edge, but you can also responsibly decide what's the best for the customer.

If this profile matches you, then find a way to get in contact with me and let us start a conversation!

I'm Andras Hatvani, a software craftsman searching for other craftsmen to execute enterprise outsourcing projects - looking forward to have you in my team!