Problem Definition
I have a Spring MVC project which is Gradle-based. I have a website project (zeario-web
), web crawler (zeario-webcrawler
), and shared classes (zeario-sharedclientserverclasses
). The web and web crawler share some classes (something like DTOs or VOs).
In my web app, I have a CrawlerController
with a getWorkUnit
method; this calls a method on a CrawlerService
instance (@Autowired
depdency), which, in turn, uses some classes from the shared library.
My problem is that I can build and deploy a working version of my web app via Gradle, but not via Eclipse. Eclipse gives me a spring runtime exception about not finding one of the shared classes, and being therefore unable to create/inject the service instance.
From the Tomcat logs:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'crawlerController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.zeario.service.CrawlerService com.zeario.api.v1.controller.CrawlerController.service; nested exception is java.lang.NoClassDefFoundError: com/zeario/api/v1/model/workunit/PageDiscoveryWorkUnit
Code Snippets
Controller definition (simplified):
@Controller
public class CrawlerController {
@Autowired
private CrawlerService service;
// ... methods with @RequestMapping ...
}
Service class (simplified):
@Service
public class CrawlerService {
public PageDiscoveryWorkUnit getPageDiscoveryWorkUnit() {
return new PageDiscoveryWorkUnit();
}
PageDiscoveryWorkUnit
is a simple POJO/Bean class. I have my service beans declared in the spring-servlet.xml
file:
<bean id="crawlerService" class="com.zeario.service.CrawlerService" />
Gradle Configuration
1) Root project (empty, no source) defines sub-projects in settings.gradle
. Dependencies are in build.gradle
:
project(':zeario-web') {
dependencies {
compile project(':zeario-sharedclientserver')
}
}
project(':zeario-webcrawler') {
dependencies {
compile project(':zeario-sharedclientserver')
}
}
2) Projects define dependencies on other projects where applicable. For example, the web project build file contains:
dependencies {
// Guava, Spring MVC, etc. ...
packed project(':zeario-sharedclientserver') // Shared code
// ...
}
Eclipse Configuration
When I check build paths, Eclipse correctly shows project dependencies; for example, it shows that the web
project has a dependency on the shared client/server
project.
It looks like Eclipse is not packaging the jar that contains
PageDiscoveryWorkUnit
into the war. This gets to how you configured Eclipse. Confirm this by unpacking the wars produced both ways and comparing the contents of `WEB-INF/lib. Then tinker with your Eclipse configuration to make sure the jar gets added.Many thanks to @Vidya who helped me realize that the issue is Eclipse, not Gradle. The problem is that Eclipse failed to copy the files into the JAR that it built.
Steps to fix this problem:
Properties
Deployment Assembly
and clickAdd
Project
, and pick the shared libraryEt viola, problem solved!
Note: Eclipse sometimes has a brain fart, and requires you to remove and re-add the project dependency. I ran into this, too.