Wednesday, January 31, 2007

Quick BeanWrapper tip

If you ever find yourself in the situation where you want to replace a single collaborator property in an otherwise fully wired environment, and all your beans are proxied by AOP, here's a handy tip.

Suppose you're testing your service component Foo, which has a dependency on service component Bar, both interfaces and transactionally proxied. Foo is wired to the actual DAOs and other service collaborators and whatnot, including Bar, but for this test purpose you'd like to replace the Bar dependency with an empty stub that doesn't do anything, or returns a fixed value or whatever. The problem is that you don't have any setBar(Bar bar) property on your Foo interface (you don't, do you? It belongs on the implementation!), so you have to employ some sort of reflection trick. After having wrapped with BeanWrapper, listed PropertyDescriptors, wrapped again, listed more PropertyDescriptors and so on, I finally found a way to modify the property on the actual Foo implementation found behind the transactional proxy:

// Here's my stub
Bar stubBar = new Bar() {
public void interactWithComplexStuff() {
// Just skip this
}
}
// Wire the new Bar
new BeanWrapperImpl(this.foo).setPropertyValue("targetSource.target.bar", stubBar);

As you can see, the property to set on the proxy is "targetSource.target.<name of actual property>".

No comments: