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:
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.
解决方案
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:
Right-click the Web project and pick Properties
Click on Deployment Assembly and click Add
Select Project, and pick the shared library
Clean, rebuild, and deploy
Et 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.