Friday, November 6, 2009

Containment vs Configuration

What is it that I don't like about xml driven configuration for spring?
I find the xml configuration duplicates (or worse doesn't) the dependencies I have configured in the project. Its basically about coding with intention, but I'll need to give you a little background.

Because I make heavy use of dependencies and fine grained artifacts (thanks Maven) containment is the natural way to define applications. If I want to use a component then I add it to the dependencies and its appears in the war. That does not mean much unless I have a way of putting them together, which is where Spring comes in.

Now of course I could now define the beans in my applicationContext.xml, but didn't I just say I wanted them? I intended to include the services from the project otherwise why add the dependency, if so isn't the extra definition redundant?

On discovery of the Component annotation and ClassPathBeanDefinitionScanner it was a natural fit. I could construct the context defined by the containment of the project and it would be that same containment defined by the deployed war.

GenericApplicationContext context = new GenericApplicationContext();
ClassPathBeadDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context, true); // true == use the default spring component filters
scanner.scan("base.package");
context.refresh();


What actually happens when this scanning occurs?
Spring will look into the Classpath from base.package down and find every class thats annotated with Component, that class will be registered with the context based on its Scope which defaults to Singleton. Thats awesome but ultimately by itself useless.

For example
@Component
public class NotVeryUsefulService {
}


Gives me a bean with id notVeryUsefulService and its not very useful. To make it useful I could give it something to play with.

For example
@Component
public class UsefulService {

private final IUsefulDataRepository usefulDataRepository;

@Autowired
public UsefulService(IUsefulDataRepository usefulDataRepository) {
this.usefulDataRepository = usefulDataRepository;
}
}


Spring has handy things called BeanPostProcessor that maniplate beans at various stages of their lifecycle. The Autowired post processor will require that a bean of type IUsefulDataRepository exists in the context or throw a BeanCreationException. This is _really_ important because it ensures the coherency of the context.

When using a decent release process like that defined by the maven release plugin, I will always verify that my context is coherent when releasing. It is simple define a test to validate this.


public class SanityTest {

@Test
public void verify() {
GenericApplicationContext context = new GenericApplicationContext();
ClassPathBeadDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context, true); // true == use the default spring component filters
scanner.scan("base.package");
context.refresh();
}
}



Environment configuration

Strategies


What does that mean?
That means that

Too many moving parts

Somehow I always seem to end up being heavily involved in deployment, and I've noticed that just like real machines software suffers by the number of moving parts. Everything you write a piece of code and need to configure it, you have a moving part.

Let me elaborate, consider your standard operations technician who takes your war and decides to have a nosey. Every piece of code thats not configured to be used is still there.

Will I ever accidentally add project with services that I don't want?
Sure its possible but what is the impact, if I define some simple processes to review things for each Release then it will be obvious.

No comments:

Post a Comment