I am new to Maven but I am trying to use it to build a project I have been working on. The setup that I require is complicated and I am having trouble getting Maven to work in the way I need it to. What I am trying to accomplish may not even be possible in Maven, but I'm sure someone with more experience could point me in the right direction.
So in my project there is one main project that includes the framework, interfaces, etc. Then there are any number of "child" modules to the main project. I put child in quotes because the child modules do not actually have a parent/child relationship with the main project, but rather include it as a dependency in order to access the framework and interfaces it contains. Each child module contains a number of classes that extend or implement a root class in the main project. The goal is to be able (from the main project) to manually look up each of these special classes in each child module, instantiate it, and add it to a list of objects held within the main project. This may seem redundant but the point is to allow additional modules to be installed and integrated as long as their classes follow the interface.
The main problem that I am running into is with dependencies, each child module could have unique dependencies that its classes use, but that the main project has no concept of. As of now, when I try to instantiate a class from the child module, I get a NoClassDefFound exception for the dependency classes, because the calling class (main project) doesn't have those dependencies listed. I believe that I need to build each child module separately into a jar with its dependencies included and access those jars instead of trying to load the .class files directly. However, the child modules will not be able to be run on their own, and I do not know if I will still have issues since it will still be getting called from the JVM of the main project.
The project is set up as follows:
| |-packages empty package placeholder for source from sub projects
| | |-src
| | | |-MainProject.packages.SubProject1
| | | | |-source for SubProject1 all with package prefix the fits into the src/packages/ in the main project
| | |-pom.xml pom for SubProject1, parent is package-pom.xml
| | |-src
| | | |-MainProject.packages.SubProject2
| | | | |-source for SubProject2 all with package prefix the fits into the src/packages/ in the main project
| | |-pom.xml pom for SubProject2, parent is package-pom.xml
| |-package-pom.xml contains settings and dependencies common to all sub projects, parent is super-pom.xml
|-pom.xml pom for main project, parent is super-pom.xml
|-super-pom.xml contains settings and dependencies common to main and sub projects
The first thing I notice is that you appear to have circular dependencies.
SubProject1 depends on MainProject for the framework and interfaces. MainProject depends on SubProject1 for the tests. This means the first thin you need to do is tease apart the dependencies. In particular, you can move the tests to a separate subproject and the framework/interfaces to a "main" subproject. Now you have an actual dependency chain where AllTests depends on SubProject1 and SubProject1 depends on MainClasses. Granted you have multiple subprojects, but that's equivalent.
This refactoring also makes it so that the parent project is a simple aggregator rather than actually having code in it. This eases your dependency troubles as well. I don't think it gets rid of them completely though. What do you want the test project to do when the subprojects have conflicting dependencies?
Can you explain what you mean by making the dependency chain? I am a little confused because there aren't any tests involved; in the MainProject there is a class called Module that other classes in SubProjects can extend. The point is that the MainProject holds an instance of all the subclasses of Module and periodically can execute() or something similar on each one. In this way I don't think it should matter if there are conflicting dependencies as each SubProject would be holding its own dependencies (that was the original goal of this set up) and they wouldn't really need to interact with any of the other modules outside the interface laid out by MainProject. It is also organised so that all of the source from SubProject1 fits nicely in the source package MainProject.package.SubProject1, I did this to help keep all the modules within the namespace of the MainProject but I think it is leading to more problems than it is worth.
posted 3 years ago
I was able to get it to run and Spring to detect the Component beans in the other projects by getting a Maven plugin to copy the dependencies of each project to the main project's lib folder. But this isn't a permanent solution as dependency conflicts can definitely occur.
The point is for any number of additional SubProjects to be installed by the user and to be automatically found and loaded on the next startup. So there is the class Module in MainProject, this contains all the basic workings of a Module object and what it must implement in order to work within the framework. Then in SubProject1 say there is a class WorkerModule that extends Module and it does some specific task, and there is also a class ListenerModule that has its own task. These both will be instantiated and run by a ModuleManager in the MainProject. All the MainProject really needs to do is call setup(), execute(), shutdown(), and the rest is specific and left up to the SubProject to define. The MainProject does not have a dependency on the SubProjects because it uses Spring to load the Module classes, and even if it loads a WorkerModule, the MainProject only knows that it is a Module object and treats it like one. Any implementation specific to the SubProject is invisible to the MainProject.
Everybody's invited. Even this tiny ad:
Building a Better World in your Backyard by Paul Wheaton and Shawn Klassen-Koop