Debugging Maven and Spring
I wanted to share an error I received with the following configuration
New application using
- Maven 2.0.4
- Eclipse 3.1.2
- Spring 2.0
- Spring-ldap 1.1
For a bunch of reasons - mainly because my company needed to standardize development lifecycle, release management and deployment - I need to use Maven 2.0.4.
I took the sample code included in the spring-ldap distribution, and created an Eclipse project. Using the Maven plugin for Eclipse. Everything would compile fine, but when I would run "mvn test" on the command line, I sporadically get this error:
Results :
[surefire] Tests run: 4, Failures: 0, Errors: 4
Error creating bean with name 'com.example.PersonDaoSpringLdapTest': Unsatisfied dependency expressed through bean property 'personDao': Set this property value or disable dependency checking for this bean.
Hmm, let me clean my Eclipse project and then run "mvn clean" and let's see what happens.
Results :
[surefire] Tests run: 4, Failures: 0, Errors: 0
Hmm. I didn't change anything. Anyway, I did some more coding and then ran the mvn test again:
Results :
[surefire] Tests run: 4, Failures: 0, Errors: 4
Error creating bean with name 'com.example.PersonDaoSpringLdapTest': Unsatisfied dependency expressed through bean property 'personDao': Set this property value or disable dependency checking for this bean.
Oh, c'mon now, what's going on! Being that there was a little lull at work and I was 100% on this project without being spread to thin on other projects, I dedicated an inordinate amount of time to debugging this - in total about 14 hours (ok, with email and lunch padding the time a little).
So I broke all the code down to the bare minimum and still got these errors. Back and forth, clean and test, I could never get a reproducible condition. Argh!!!! Google searches on the "Error creating..." message above never really revealed much.
Without bogging you down (as if I haven't already) with debugging details, here's what I found.
It hit me during a long walk that there is some class-loading conflict.
Using spring's AbstractDependencyInjectionSpringContextTests class for loading spring files, I was wondering whether maven was having a problem finding the file
protected String[] getConfigLocations() {
return new String[] {
"classpath:/**/applicationContext-springldap.xml"
};
}
Here are the conditions:
- If no file is found, you will not get an error saying "file not found", and instead will get the "Error creating bean..." error.
- If the file is found, everything should work
To alleviate this, try using more defined criteria for finding the file
protected String[] getConfigLocations() {
return new String[] {
"classpath:/com/example/applicationContext-springldap.xml"
};
}
Now, if the file is not found, you will get this (note, I intentionally renamed the file:
IOException parsing XML document from class path resource [comm/example/applicationContext-springldap.xml]; nested exception is java.io.FileNotFoundException: class path resource [comm/example/applicationContext-springldap.xml] cannot be opened because it does not exist
Ok, so I began to realize that Maven did something with "resources". After never getting very far with Maven (see many of my previous posts), I forgot that Maven used this src/main/resources directory to store configuration files like the Spring xml file.
Going back and using Clean in eclipse, then mvn clean, my tests again failed. Looking in target/classes, I realized that it was not finding my applicationContext-springldap.xml file.
I looked in the project properties under "build path" in eclipse and expected to see the default project/bin directory set up for classes. No! After enabling the project for Maven using the plugin, apparently it changes it from project/bin to project/test-classes. Argh! Ok, so I switched it to project/bin.
Now I've got the class loading separate between eclipse and maven so there should be no interference. In my src/main/java, I kept the applicationContext-springldap.xml amongst the java classes because well ... that's how example was packaged. For compilation, Eclipse brings this xml file to project/bin, but Maven doesn't.
In order for the Spring config file to be loaded, you need to put the Spring file in src/main/resources. And if you want to still use this:
protected String[] getConfigLocations() {
return new String[] {
"classpath:/com/example/applicationContext-springldap.xml"
};
}
Then your file needs to be in src/main/resources/com/example/applicationContext-springldap.xml.
After doing this, all is well. It turns out the error had nothing to do with Spring-Ldap, as I originally thought.
Sorry for being long-winded, but I wanted to give the error message some context, since context is the one thing I couldn't get in my builds or in any google searching.

3 Comments:
Nice post. I do a lot of using testing with Spring as well, but I list the files explicitly instead of using a wildcard.
Anyway, looks like this post is a year old. Any plans on posting some more? :)
BTW - I learned how to make a Maven plugin. I posted an entry on the cookbook site so that I don't forget how I did it. It was actually really simple. http://progcookbook.blogspot.com/
God bless you, good man, for your most helpful post! I'd never had figured it out myself that "Unsatisfied dependency" might simply mean Spring not finding file. Same issue here. Thanks again!
Thanks for posting this article.
Post a Comment
<< Home