Dec 06

The in-laws gave us the nicest present ever…

Personal 2 Comments »

Comedians have got easy laughs from “in-law” jokes through-out the years.

However, my in-laws, just gave us the best gift ever.

I have been out of town working on a project, and my wife has been working really hard, in the tough job that is: teacher.

My wife met me out of town for a weekend (seeing my family), and when we got home something ‘felt’ different.

The ENTIRE house had been cleaned.

And not just a quick pick up:

  • Laundary: done
  • Any mess: picked up
  • Floors: cleaned
  • Bathrooms: glinting
  • Blockbuster movies: taken back to the store

I have an amazing family!

Dec 06

Injecting Dependencies: My Test Classes Want Injection Too

Tech 9 Comments »

I like injecting dependencies. It makes my code a lot cleaner and easier to deal with.

So, when I find a service locator lookup method such as a Spring getBean("foo), my nose turns up a little.

On a current project, I see these getBean() calls in various JUnit tests. The Spring Beans themselves often have a public field called springBeanName, which the test goes too, to look up the right bean.

Initial Code

This meant that the code looked like this:

A Base Test Case class has within it:

  • Code to configure logging
  • Code to setup Spring:
    String[] paths = {"classpath:applicationContext*.xml"};
    ctx = new XmlWebApplicationContext();
    ctx.setConfigLocations(paths);
    ctx.setServletContext(new MockServletContext(""));
    ctx.refresh();
    
  • Some mock objects which various test classes can grab
  • Helper methods to get Spring managed beans. E.g. a DAO:
    protected UserDAO getUserDao() {
    return (UserDAO) getBean(UserDAO.springBeanName);
    }
    

Then a test itself will extend the base class, and either grab a bean from a helper method, or do a getBean() themselves.

Injecting into JUnit classes

I want to be able to put my set/get injection methods on my test classes, and have Spring do the rest.

Luckily, Colin and Dmitriy pointed me to org.springframework.test.AbstractDependencyInjectionSpringContextTests, which likes to hang out in the Spring Mocks package (not core Spring).

It simply allows you to bootstrap your test class, and have Spring wire you up nicely. I changed my BaseTestCase to now implement this abstract class, and overrite the method which returns the config locations. Something like:

protected String[] getConfigLocations() {
return new String[] { "classpath:applicationContext*.xml" };
}

Now, in my test cases I setup a get/set combo for the types that I wish to inject. For example:

public class AddSiteTest extends BaseTestCase {

public void testAddingValidSite() throws Exception {
TestCase.assertEquals("AddSiteTest action did not return SUCCESS", Action.SUCCESS, getAction().execute());
}

// ------------------------------------------------------------------------
//  Spring Dependencies: BaseTestCase will autowire by type
// ------------------------------------------------------------------------
private AddSite action;

public AddSite getAction() {
return action;
}

public void setAction(AddSite action) {
this.action = action;
}

}

What I really want: No auto-wire, let me wire it

This has got me pretty much what I wanted. My test classes not have dependencies injected. However, I kinda want one more step.

Rather than wiring up automatically by type, I would rather:

  • Create a test-applicationContext.xml which has the wiring of test classes: E.g.
    <bean id="addSiteTest" class="foo.web.actions.AddSiteTest">
    <property name="action"><ref bean="addSiteAction"/></property>
    </bean>
    
  • Create one get/setAction in the BaseTestCase:
    private Action action;
    
    public Action getAction() {
    return action;
    }
    
    public void setAction(Action action) {
    this.action = action;
    }
    

With this configuration all of my tests could delve and grab the action via getAction() without having to do anything else. For this to work, I am basically asking Spring for an API like:

injectDependencies(Object toInject, Spring beanIdWithWhichToGetDependenciesFrom, …);

E.g.

injectDependencies(this, getMyBeanId(), …);

Then in the given class you could override getMyBeanId(), or you could default to “my class name with the first letter lower-cased” for ease of use :)

NOTE: You can auto-wire by name:

Declare protected variables of the required type which match named beans in the context. This is autowire by name, rather than type. This approach is based on an approach originated by Ara Abrahmian. Setter Dependency Injection is the default: set the populateProtectedVariables property to true in the constructor to switch on Field Injection.

Anyway, I am just glad to have Spring watching my back on the testing side too…

Dec 03

Microsoft gets into the blogging world with MSN Spaces

Tech 1 Comment »

I thought it was interesting to see the launch of spaces.msn.com.

It is basically a blog + a place to store pictures, music, etc.

Pretty nicely done… but not too much new

MSN Introduces New Communication Service That Enables Blogging, Picture Sharing and More

REDMOND, Wash. – Dec. 1, 2004 - The MSN

Dec 02

Inverting Brian’s Mind

Tech 1 Comment »

In Inverting the Inversion of Control he discusses an interesting melding of AOP.

He mentions a mechanism where you tweak bytecode so doing a new() doesn’t just create a new type.

I have seen this before, especially in the AOP world where some people use this to make new a factory. It also opens up the power that you get in more dynamic languages. When you do a new it may do some logic and return a subclass of the actual class you asked for etc.

The worry that I have had in Java is when people make new act like a singleton. That is scary as when you say new you really think that it will mean new memory on the heap etc etc.

However, back to Brian. How cool would this be:

update
methods
set
method_body='return new Integer(42);'
where
package = 'org.example.foo' and
name = 'getDayOfWeek';

i love adding fuel to fires :) :) :)

Dec 01

Groovy mavenisms again: Building a lib dir from dependencies

Builds, Groovy, Tech 1 Comment »

To follow on in the same vein as my last post, I also have had the need now and then to take my maven world, and build a lib directory snapshot of my projects dependencies to pass on to others.

This was used with people not using maven, and for awhile for my IDE to point too (although now I can % maven idea). The only annoying part of maven idea is that it whipes your config each time, and you can’t share the project as the files are all absolute to your own personal maven repo.

Maven Jar Builder

#!/bin/env groovy
# -----------------------------------------------------------------------------
# maven2jar.g: Take a given project.xml and build a directory with jar files
# -----------------------------------------------------------------------------

import groovy.util.XmlParser
import java.io.*
import java.nio.channels.*

# -- Enforce the project.xml and dir
if (args.length < 1) {
println """
Usage: maven2jar.g project.xml [newdir]

e.g. maven2jar.g /foo/project.xml tempdir (defaults to .)
"""
System.exit(1)
}

# -- Variables
projectxml   = args[0]
todir        = (args.length > 1) ? args[1] : ".";
badFiles     = []
mavenLocalRepository = System.getProperty("user.home") + "/.maven/repository"

# -- Open up the file and do the work
project = new XmlParser().parse(projectxml)

project.dependencies.dependency.each {
groupId    = it.groupId[0].text()
artifactId = it.artifactId[0].text()
version    = it.version[0].text()

fromFileName = "${mavenLocalRepository}/${groupId}/jars/${artifactId}-${version}.jar"
toFileName   = "${todir}/${artifactId}-${version}.jar"

println "-----------------------------------------------------------------------"
println " Copying From: ${fromFileName}"
println " Copying To  : ${toFileName}"

try {
copyFile(new File(fromFileName), new File(toFileName))
} catch (Exception e) {
println "Error: Could not copy: ${e}"
}
}

# -- Define the function to copy the files
def copyFile(inFile, outFile) {
FileChannel sourceChannel = new FileInputStream(inFile).getChannel()
FileChannel destinationChannel = new FileOutputStream(outFile).getChannel()
sourceChannel.transferTo(0, sourceChannel.size(), destinationChannel)
sourceChannel.close()
destinationChannel.close()
}