I am still fairly new to Maven, I finally have it how I want but now I need to break it all over again.
Here is my scenario:
I need to write two different server applications, which use identical core functionality; just, what is done with that framework is very different. One server application is very easy/simple - it's already done - whereas the other is a lot more complicated.
The code is written in a dependency injection style (using Guice, if it matters), so it should be extremely easy to break apart.
My question is this: how would you structure the projects in Eclipse, using Maven? Would you set up three different projects, something like:
server-core
server-appEasy
server-appComplicated
where each server would have it's own pom. Or, would you keep it all in one project? I need to be able to easily recompile appEasy in, say, a month from now, while I work on appComplicated. The classes for appEasy are already in a subpackage. Note: core would not work by itself without at least a mock dependency injection. It doesn't have a main class.
All thoughts appreciated, even on things I haven't thought of.
I would have a structure like this:
/server
/server-core
pom.xml
/server-appeasy
pom.xml
/server-appcomplicated
pom.xml
pom.xml
So each project has its own pom.xml that allows you to build that project in isolation.
However the parent folder also has a pom.xml, which will build all the projects if run. You can do this by including the projects as modules in the parent pom.
E.g. In the parent pom.xml
<modules>
<module>server-core</module>
<module>server-appeasy</module>
<module>server-appcomplicated</module>
</modules>
You can also use managed dependencies in the parent pom tio allow you to centralise external dependency and plugin version numbers.
I would suggest to structure all as a Maven Multi Module project.
The parent project, would have the three projects as modules, the 3th party dependency versions, and the version of your project as a property.
Then, in the server-appComplicated and server-appEasy I would add a dependecy to the server-core.
In this way you will gain:
1- A root project to compile (the parent), that it will generate the two servers and the core-lib.
2- A point where to handle the version numbers and the common dependencies.
I hope it helps
Im not a maven expert but here is my 2 cents.
Each project needs its own pom.
Do you need to build all the projects together? In that case it might make sense to have a parent pom , which has all the common dependencies.
EDIT: In that case, I feel just have three separate 3 pom files for each project.
There are multiple ways to do this, depending on how you need it when it comes to deployment. Assuming that 'server-core' is a shared artifacts among your 'server-appEasy' and 'server-appComplicated' artifacts, I would suggest something as below
Create a Maven Project 'server-core'
Add two module projects
by name 'server-appEasy' and 'server-appComplicated'
Make sure the module projects have their parent set as the 'server-core'
In the end you should have three projects (each has separate pom.xml), where
a. Building 'server-core' will also build the modules
b. Building either of the 'easy' and 'complicated' modules independently on need basis will also build the server-core.
Hope this helps!
Related
At the moment I'm working in a project which contains out of 260 maven submodules under one parent pom. This seems to slow down the build. That's why I came up with the question when should I use submodules and when shouldn't I use it.
Introduction to the POM says:
If you have several Maven projects, and they all have similar configurations, you can refactor your projects by pulling out those similar configurations and making a parent project. Thus, all you have to do is to let your Maven projects inherit that parent project, and those configurations would then be applied to all of them.
And if you have a group of projects that are built or processed together, you can create a parent project and have that parent project declare those projects as its modules. By doing so, you'd only have to build the parent and the rest will follow.
Create submodules when:
projects share the same configuration, to avoid configuration duplication
projects are interconnected, to make building easier
This question is a bit broad because it is hard to set a general rule.
My rule of thumb:
"A multi-module project consists of those modules/artifacts that should always be built together".
If you just want to share configuration, you can use a parent POM without using multi-module.
I'm developing on an java application that consists on a main-application that is loading extensions (jars) at runtime. Each extension is a java project.
all jars have the main application in class path and other libraries. The manifest of the main application also has dependencies in the manifest classpath, e.g. sqldriver, poi,log4j etc.
Everytime I change on of the lib, i have to set all classpaths of the projects. Also if i want to build all the jars, i have to export each project once.
So I thought maybe is Maven a good solution for me. So I've installed m2eclipse and converted the projects to maven projects.
But for now i have for each projekt an own pom.xml and i also have to build all projects once.
I'm new to Maven and searching for best practises for my problem. So I'll thank you for your help and advice
Make all your projects modules of one parent pom project. This way you can build them all at the same time.
You can use a hierarchy for your pom files. Here's an older question (similar to yours) that has a great example in the answers:
Maven: POM modules and submodules hierarchy
Basically this structure:
<project>
<parent>...
</parent>
<artifactId>module</artifactId>
<packaging>pom</packaging>
<name>Module</name>
<modules>
<module>submodule</module>
</modules>
(...)
</project>
in a 'root' pom.xml file, besides the actual submodule pom.xml files.
Unless you really, really need OSGi , Maven is great. If you're doing OSGi maven is less great.
M2eclipse however is less helpful, and in my experience only leads to confusing headaches.
How you should build your projects depends on a few things. I agree that the submodule approach described in the other answers is best-practice, and if all your sub-module candidates are related (for instance, each represents a tier in a n-tiered application), in the same SCM repository, and the interfaces change often, and the versions are co-dependant then by all means, you should do that.
If however your submodules are stand-alone and don't have a lot of transitive dependencies, particularly if they are in separate SCM repositories, they are independently versioned, and you have a little spare hardware for a build server (like say Hudson) and a Maven2 artifactory (like Sonatype Nexus), you could just keep them as seperate projects, and let maven handle the rest. This way you avoid having to re-build everything because you made a small change in one of the submodules. You can just build that one.
I have 3 Java projects with the same entities.
I want to share entities between these projects because entities can evolve during the development phase.
We are thinking about building a jar with entities and sharing it using Maven (with a repository).
Maybe you have another solution ?
I also can recommend to use Maven to share code between projects.
Here are some tips to get started:
Use a Maven Repository Manager such as Nexus. It will help you to
create a stable development environment.
Every developer (also the Continuous Integration Server user) should configure their settings file to use your Maven Repository
Manager. Don't specify your repositories in the POMs, confiugre them
only in your Maven Repository Manager.
http://www.sonatype.com/books/nexus-book/reference/maven-sect-single-group.html
Use the dependencyManagement and pluginManagement elements of your parent POMs to specify all versions of the plugins and dependencies
you are using. Omit these versions in the other POMs (they will
inherit them from the parent POM).
I also recommend to use different POMs for multi-module builds and parent POMs.
If you want to share common interfaces, classes, functionality or components, Maven is the way to go. In addition to the dependency management, you also get the added bonus of a standard project layout that will simplify things. Easy integration with most common continuous integration servers and a standard release process are further benefits.
Definitely take a look at Maven!
making an own JAR-library is definitely a good solution.
The jar-file is easy to distribute via dependency management (maven, ivy, gradle ..)
The jar is versioned
The projects using the library can be tested against a certain verion. Otherwise it may gets a problem if you change enties and forget to change a depending project. -> integration tests
Regards
Entities are the representation of a given object am I correct? If so the default mechanism implemented by Java is Object serialization - http://en.wikipedia.org/wiki/Serialization. In the case of jar files if an entity changes you would have to change jar once again each time as well. It may be tedious.
Geneate a standard war file in roo.. But then change it's package to jar file.
Then from any standard war file you can just deploy this jar (Ill use the jar as a maven dependency). Ill maintain a unique named applicationConext like pizzaShop-applicationContext.xml and like pizzaShop-applicationContext-jpa.xml. so from a parent spring project I can stack up various roo projects in this fashion.
Ill also keep their generated webapps folder to allow for the generator to work more easily. (This means I have to open up the pom.xml and keep changing it back to jar). Also helps with cut and paste fodder for non roo generated war files web.xml entry additions.
Seems like it may be a confusing point about roo.. You can just mix and match these jars as you would any spring project. They function like self contained units of springness and work fine sitting side by side with other spring jars all under the same webapp/web.xml context.
Its tedious but still better then writing spring code by hand.
I have a small (4 module) maven project with the root pom in pom packaging. Right now, I have a impl module that contains the main methods and setup. This does lead to some issues, eg building a single jar for the entire project, (possible) huge dependency list containing all modules, and confusion trying to trace back to the main method for future developers.
So I'm thinking: Is it best practice to put this kind of stuff in the root project, or should it stay in its own module? Would there be any disadvantages of putting it in root (eg plugin issues)?
This does lead to some issues, eg building a single jar for the entire project
There are solutions for this (e.g. using a dedicated module and the Maven Assembly Plugin or the Maven Shade Plugin).
(possible) huge dependency list containing all modules,
I didn't understand what you're referring to here.
and confusion trying to trace back to the main method for future developers.
Just document things if nobody can transmit the information.
So I'm thinking: Is it best practice to put this kind of stuff in the root project, or should it stay in its own module? Would there be any disadvantages of putting it in root (eg plugin issues)?
Stephen is correct, aggregating and/or parent POMs must have a packaging of type pom and you can't put any code in them.
AFAIK, the parent module of a multi-module project has to have type "pom" and that would preclude putting any code or other resources into it.
Certainly, I wouldn't try this.
If you want to have all of your classes, etc assembled into a single JAR, there are other ways of doing this. For example, take a look at the Maven Shade Plugin.
Our software is written in Java and comprise many (7) projects.
These projects are Netbeans ant projects.
I'm considering to converting them to maven2.
Where can I find some hints for doing such thing?
Don't read that book. It will only make you confused. Read this book instead: "Maven - The definitive guide" http://www.sonatype.com/books/maven-book/reference/ .
Also, the maven site has a lot of information, but the structure is terrible so you'll need to use google to navigate in it.
Here is my suggestion:
Do this by hand, not with "automagic" "help" from the IDE. Maven integration doesn't work that good yet, not in any IDE.
Make sure you program project is divided into modules under a common umbrella module, so that each module produces a single binary artifact (jar, war,...) possibly accompanied by the javadoc of the source code behind that artifact, a zip with the source code etc. The basic principle is that each module produces a single artifact, containing all the non-test-code under that module. You can do this while the project is still built by ant.
Each module should conform to the standard maven directory layout. The build destination is under [module]/target/[output-type, e.g. "classes"]. The source code is under [module]/src/main/[src-type e.g. "java"] and [module]/test/[src-type]. The artifact consists of all the code under src/main, and none of the code under src/test, as it built to the target directories. You can do this while the is still built by ant.
Start by transforming the sub-module that has no dependencies on other modules in the project.
Now you can create the parent maven module pom.xml with artifact type "pom", consisting of one of the modules below. Make a child module for the first submodule (the one with only external dependencies), using the umbrella module as "parent". Remember that you need to specify version for the parent. Remember to add the child module as a "module" in the parent too. Always use ${project.version} as version in the child modules when you create multi-module projects like this. All modules under a parent must be released simultaneously in a single operation, and if you use this setting maven will make sure the version fields stay the same across all modules and gets updated everywhere during the release. This may make it difficult to re-use the existing numbering scheme, but that doesn't matter. You are never going to run out of version numbers anyway.
Add the necessary dependencies, and make sure you can build the parent and the child module together using the command "mvn clean install" from the parent module.
Proceed with the rest of the modules the same way. Dependencies to other modules under the same parent project should also use ${project.version} as the "version" they are depending on, meaning "the same version as this". NOTE THAT in order to build, the module you are depending on must be built using "mvn install", so that it gets deployed to you local (computer) repository. Otherwise the depending module will not be able to find the classes. There are NO source-code dependencies between modules in maven, only dependencies to built and packed versions installed in local and remote repositories. This can be very confusing if you come from ant-projects. Build from the root module until you get comfortable with this. It takes two days.
Don't use maven integration in IDEs. It is a bad idea. Use "mvn idea:idea" or "mvn eclipse:eclipse" to set up your workspace as a non-maven ordinary IDE project. The inter-module dependencies mechanisms in maven and the IDE aren't identical and will never be. Also, if you have several mavenized projects with dependencies in between, you want to have several of these in your workspace with dependencies set up between. You can do this with mvn idea:idea / eclipse:eclipse if you create a separate maven project file called "workspace.xml" (or whatever) in the same directory as parent module, set up as a multi-module project containing modules "." and "../otherproject" (only one-way reference here, no parent ref back). If you run "mvn idea:idea / eclipse:eclipse -f workspace.xml" you get a workspace with all these modules linked together. No IDE integration lets you do that. This sound like a lot of extra work, but the workspace.xml-file is really small. It doesn't have to contain all that dependency stuff and all that, only the reference to the modules you want to bind together in your IDE.
I did a succeful migration of NetBeans Ant project to Maven project using the instruccions by Joseph Mocker here: http://forums.netbeans.org/ptopic55953.html
I cite the important part:
close the project
rename the build.xml, nbproject files/folders to something so NB won't recognize them.
close and restart NB (so any memory cache knowledge of the project is gone)
copy in an empty pom from some other project.
open the project back up in NB (NB should now identify it as a maven project)
rearrange the files to follow the maven way (™)
This won't be an easy task since Maven2 expects the files to be organized in a specific way. Anyway Better Builds with Maven is a free book that should get you started. It will help you understand Maven and it also has a chapter on migration.
I discovered that the migration is not necessary. The real requirements that I need was automatic download of dependencies (libraries).
This is also achieved by Ivy which nonetheless uses maven repositories.
I solved converting project from ant to ant+ivy with IvyBeans.
I have built a script to migrate Ant builds to Maven. You can find more information here:
https://github.com/ewhauser/ant2maven
It won't help you with fixing your directory structure and or any additional Ant tasks, but it removes a lot of the tedious steps to get started.