Spring can't find class from shared Gradle lib

2019-08-07 11:48发布

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.

2条回答
虎瘦雄心在
2楼-- · 2019-08-07 12:13

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.

查看更多
兄弟一词,经得起流年.
3楼-- · 2019-08-07 12:22

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.

查看更多
登录 后发表回答