I am in need of separate jar of some classes existing in a multi-module project. I need to pull those classes out of existing module so that I can create a jar for them which I can then export to some other project. What I am thinking is what's the advantage of creating separate module in existing project or altogether creating a separate project?
I can't think of possible trade-off. Can you tell me the trade offs involved.
I would suggest you to create an another module instead of a separate project.
Justification:
1) You can pack this jar and use wherever you want it.
2) You can add this module as a dependency to the other modules
3) We will be following the the Maven general rule "one primary artifact per POM"
Conceptually, you should only create a new project if the set of classes you're moving are coherently useful. If this new project you're going to create can be used to solve a problem (with a good API), I think it's a good enough reason to create a new project.
Otherwise, it's perfectly fine for a maven artifact to be shared among other projects even it is just a module of a multi-module project.
Just my $0.02
module:
- easy to manage dependencies
- easy to support shared components. For example two modules use the same
database.
- build/ci process may take longer
project:
- you can easily deploy projects separately with their own versions and so on
- more convinient in case a dedicated team works on a seprated project
- easy to manage build system
- more complicated to handle dependencies
Related
Background:
I have multiple projects that utilize the same logic across their business so I decided to split the shared part and reference it in both projects.
Example:
Suppose there is an HR application and an Accounting application that require a shared business in this case let's say count hours which is part of calculations class (let's call it calc).
Both applications (HR & Accounting) have their own repository on gitlab. Also have independent deployment and utilize the calc package which is uploaded on nexus repository.
Question:
I would like to know if there is a way to find projects using calc package through the package name across the repositories.
If you have the projects that you want checked out locally, you could find the dependency-tree for each project:
mvn depedency:tree
This gives you all the (transitive) dependencies that are used the projects. If you do this for each project and then grep your package-name, this should find you all projects that use it, or at least have a dependency on it.
I am not sure how to calculate dependencies through package names. But:
If you have access to the source you can scan your projects for pom.xml and find the dependencies
If you have access to the runtime libraries you can scan these jars for /META-INF/maven/*/*/pom.xml and check the dependencies
Either way you should be able to find jar files making use of Calc.
There is no way to ask Calc where it got used from.
Never found a really satisfactory solution to this. How do you do it? I am looking for inspiration for new approaches.
For context, assume I write a generator that takes a project resource and generates a code file. But it could be any other project support tool - validator, converter, deployer etc. Often manually triggered actions that are not running as part of normal build.
Such tools typically require a few dependencies that are not required by the project itself at runtime.
Strategies that I have applied or considered in the past:
add tool dependency to project anyway, and either mark it "provided" or filter it out during the packaging process (this is what I usually do, but now I am in danger of adding normal project code that uses the tool dependency, potentially resulting in an error that only manifests during runtime)
use a script (trying hard to avoid scripts and their hidden dependencies and complexities)
create separate support projects (trying hard to avoid project explosion, especially for seemingly small tasks that are handled by a few lines of code)
subprojects / modules (only vaguely aware of this option, never really tried it)
maven plugin that is run with a profile with separate dependencies (trying to avoid the separate project required to maintain the custom plugin)
Inspiration from answers and comments
separate tools project shared by multiple projects
I just realized that maven and eclipse already solved exactly this problem for a very specific "tool": test code.
Test code often needs additional dependencies not used by the application itself.
People obviously invested quite a bit to keep the "test / tool" infrastructure within the same project, as opposed to creating a separate test-project:
separate source locations (src/main/java, src/test/java)
separate resource locations (src/main/resources, src/test/resources)
a full-blown separate maven dependency scope "test", complete with transitive resolution
separate compilation phases (compile / test) with separate dependency trees
eclipse supports special junit launch configurations that are able to correctly resolve the test dependencies
probably more stuff that I am not aware of currently
So, I am strongly considering to program all my supporting tools as "junit test cases".
I am planning to create and commit shared junit launch configs for the team that execute just one specific "test case", which will run the tool logic instead of testing.
The problem I have to solve is to avoid running these dummy tests during the normal maven test phase.
Also, writing this, I realize that there is even another such system already in place: the maven plugin infrastructure, that also has a separate dependency resolution mechanism. Although, so far it seems necessary or normal to create separate projects to create plugins. I will look into ways of writing and building project specific maven plugins without needing to create separate projects. I am thinking about generating the pom.xml needed for plugin compilation on the fly, and including all the test dependencies.
I have three separate gradle projects. In these projects I have some code that is common to all of them. What is the best way to create common library.
I do not want to install and maintain maven repo
I know that I can create jar file and add it to all three projects but then I will need to manually add new jar after every update.
If there's any more than one person on your team you should have a continuous integration server which is publishing artifacts to a repository. You then have the option to
Develop one project and reference the other from the repository
Develop on two projects in parallel using a composite build
If it's just you then I guess you could do one of:
Publish to mavenLocal() and lookup from there (see publishing to maven local)
Create a composite build from two or more projects
I'd argue that even if a single developer, you should have a CI server that's constantly building and reporting test failures. So it's logical that this should be publishing to a repository too.
I wouldn't qualify it as "best" by any stretch, but I think you could "publish" your common lib to a shared drive and then have the other Gradle builds use a Flat Directory Repository to depend on it.
Good luck.
Well here is an interesting experience i had since last couple of weeks structuring my maven multi module project.
When i decided to use maven for my build life cycle management i had couple of reason that i wished to choose maven.
a. Mostly development teams are divided so that each team can work on separate Module within the project like Team-A to work on User Management System, Team-B to work on Authorization System, Team-C to work on Document Management System...and so on. Each team has java developers, testers, UI experts etc.
So the maven Project structure should be such that each team can independently work on their respective modules. They must be able to code, compile, build, test, deploy their module without having to compile, test modules belonging to other teams.
And thus i came to conclusion that each development module of the maven multi-module project must represent a Functional Module
After some discussions on forums i found people suggesting me to follow layered approach were child modules must be layers like controller-layer,service-layer,dao-layer etc. I did not pay heed to this advice because this not solving my purpose of teams working on individual module. This way for large project the build and deployment time for each team during development increases which does impact the project time-lines. sometimes the build and deploy time is upto 30 minutes say if there are 10 to 11 modules in the project.
But i did pay heed to a suggestion that keeping DAO layer separate for each module is not a good idea as DAO is highly granular and reused by other modules. and so the dependency of one module on other would would any how become greater.
I found a solution to this problem by creating a common module and moving DAOs and DOMAIN to the common module which will be inherited as a dependency by each module. And this seems to be a more viable option. Now the Project Structure looks like this.
Now when i build the project and run the webapp on server, It complains 404, Resource Not Found. I found that this is because the WEB-INF/classes folder is missing, src/main/java is missing in web-app module. I searched and found couple of links that suggested it is Deployment Assembly issue in Eclipse. So i need to manually create these folders and add in the deployment assembly because maven does not do it.
But the bigger questions are
do i need to move the Controller classes like com.mycompany.usermgmtsys.controller.UserMgmtController etc.. to src/main/java Or maven should find the controllers from the module jars included as dependency in WEB-INF/lib.
I dont want to do this i.e. putting java file in web-app. i want all the controllers should be available to the web-app as dependency for example WEB-INF/lib/usermgmtsystem.jar. But then wouldnt the Tomcat be looking for controllers in classes folder.
I dont know what should i do ? Any suggestions would be appreciated.
Its the way the eclipse render maven based project. It generally creates two structure. One based on master pom (parent project) and others based on individual module pom. however doing changes in any structure will reflect in the other one. As a practice I do changes in individual module folder structures and is more easy to read too.
Personally I try to avoid multi-module projects as, if you're using the Maven Release Plugin, you are locked into releasing all your modules together.
While this may sound like a convenience the problem arises when you need to do bug fix release to one of the modules - you end up releasing all the modules, not just the module with the bug fix, incrementing their version even though they haven't changed.
You also take a hit if you're running CI with multi-module projects - you're build typically runs over all modules from you root pom but if you're working in a particular module, you end up taking the hit of building those that haven't changed, in effect losing some of the benefits that the modularization was meant to provide.
So, go with independent modules but, and this is the important bit, create a common 'dependency' pom used by each.
A 'dependency' pom is a pom that standardizes all the dependencies across your projects and is different in that those dependencies are specified in the dependencyManagement section rather than the dependencies section (it also sets up standard plugin config, etc). This allows your project poms to specify the dependency pom as their parent and then declare the dependencies they need minus the versions, which are picked up from the 'dependency' pom and thus standardized across your projects.
If you are still concerned about being able to built everything, this can be achieved with a simple batch-file.
This is a good question. There are many aspects that must be considered for a useful project layout. I'd like to try to answer one which you didn't mention. Is your app extensible by users? If it is, then consider creating a separate module for your public API layer (service interfaces, DTOs used by those services, and Exceptions thrown by the services).
In our app, we have several maven modules per functional area. The idea is that a group worked on a feature within just one functional area and this isolation kept them messing with sources being modified by another group. Each functional area is broken down further in maven sub-modules we call "api", "domain", and "service" - we don't lump services/controllers, domain, and exceptions into a single module. The api module contains those classes we want to expose to customers for their customizations. Our service layer is the implementation of those interfaces. Further, we do not allow one module's service to call another module's service as this would bypass our service orchestration layer where customer can attach extensions to our services. Using separate maven modules per functional area helps enforce this.
We have other modules (internal-api, web, adapter) but they don't really add to this topic.
I figured out the issue. Controllers are presentation-layer components. The dispatcher expects the presentation layer components in the WEB-INF/classes folder in the target rather than looking for it in the lib. I am not sure if this is valid only for maven based structuring in eclipse. So finally these are the changes i have made
a. Created a src/main/java source folder in web-app. It is not generated by default in web-app module.
b. Add packages and respective controllers in the src/main/java folder.
So the final structure that i have (i am not pasting exact eclipse snapshot, this is generalized view)
I develop a little java utility library using maven. Now I'd like to add some demo / sample code to show how to use the library.
Where is the best place to put it?
In a sub-package with the other code. I don't like this since it means the demos will be included in the library jar file.
In a new maven artifact. That works, but I'd prever to have the demos closer connected to the library source.
As a sub-artifact. Haven't tried this yet. Seems to make everything a bit complex for something that should be simple.
Is there any common pattern to do this?
If it's some sample code snippets that run by themselves and just demonstrate how to use the library, then write them as unit tests, in the same module.
If it's more like a separate demo application (that a user might even interact with), then create a separate artifact. It's the standard way of doing it. If you really want to you could put it in the same module, but in a different source directory, but that's just making it harder on yourself.
Your library and you demo should probably share a parent module (of type "pom", not "jar" like the others), giving you a multi-module project. Then you can build both by launching maven from this parent module.
If you want to release your library and demo together (you can, but you don't have to), you can do that from the parent too.
In other words, it's not because they are separate modules, packaged in different artifacts, that they cannot be closely connected anymore. The different modules of a multi-module project still form one whole project.
You hadn't written what kind of utility library it is, but if it's something like apache commons, then most of the demos can be written as JUnit tests, which are placed in the same artifact. Good designed JUnit tests both tests your code and provide example how to use your utilities.
I prefer a new maven artifact, it can make your own artifact clean
I would recommend create a maven multi-module project where one module is the core and one module is the demo code. That way the user can choose if he wants to create both modules (they become separate artifacts) or if he just wants the core.