Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Maven naming conventions for hierarchical multiple module projects

I've got a question on Maven naming conventions (groupId, artifactId and directory names) in a multiple module project with a hierarchical directory structrure.

Research

Before asking, I went through other the web on this topic and what I cleared out for myself:

  1. Possible duplication for my question, but it does not cover multiple-hierarchy levels.

  2. Project directory name should match artificatId.

  3. Guide to Naming Conventions provide examples:

    • groupId will identify your project uniquely across all projects, so we need to enforce a naming schema. It has to follow the package name rules (eg. org.apache.maven, org.apache.commons, org.apache.maven.plugins)

    • artifactId If you created it then you can choose whatever name you want with lowercase letters and no strange symbols. (eg. maven, commons-math)

This is quite straightforward and I understand it, but there are few things that are still unclear.

artifactId examples mentioned in conventions can be applied only to one-level hierarchy module.

Examples

I went through maven repositories and extracted some examples:

Spring mostly uses names: spring-core, spring-context, spring-context-support. All standalone modules are one-level hierarchy and spring- prefix for search efficiency. There are no problems, since hierarchy is not that deep.

Apache CXF namings are quite unconventional for Apache. Artifacts are standalone modules with up to 5 possible different artifacts in names eg. cxf-tools-wsdlto-databinding-jaxb.

There are lots of artifacts (cxf-rt-databinding-jaxb, cxf-rt-databinding-aegis, cxf-rt-databinding-xmlbeans, cxf-rt-databinding-sdo) which could be grouped in multiple module project (cxf-rt-databindings), but they didn't and so the names became spaghetti.

Finally, Maven Plugins is first a multiple module project (after org.apache.maven) which has artifacts like: maven-compiler-plugin, maven-enforcer-plugin.

There are quite a lot of examples and the all follow different conventions on naming artifactIds (consequently project directories).

Outcome

Taking best practices from the examples let us review hierarchy levels.

One-level hierarchy naming would be (

groupId:    org.organization.project artifactId: project-portal ---.                               |                               project-portal-service                               |                               project-portal-plugins (continued on next diagram)                               |                               project-portal-util 

(continued) two-level hierarchy would be:

groupId:    org.organization.project.plugins artifactId: project-portal-plugins ---.                                       |                                       project-sample-plugin                                       |                                       project-another-great-plugin                                       |                                       ???? (multiple module project) 

You see question marks? Thats where the

Questions

I followed conventions from examples (ignoring spaghetti Apache CXF example):

  • Root - project-portal (eg. spring-core, maven-core)
  • First-level hierarchy names inherit from root - project-portal-plugins (eg. spring-context-support).
  • Second-level hierarchy names - project-sample-plugin (eg. maven-compiler-plugin).

And now we are stuck on third-level, like in old games without saves and checkpoints.

  1. Is this the right directory naming path taken from Maven examples for deeper hierarchy levels?
  2. Are there any conventions or rules you follow to support simple directory and artifact names avoiding spaghetti names on deeper levels?
  3. If there are simple names, will groupId save duplicated artifact names (which will occur due to simplicity) from collisions in repository?
  4. What about searching and finding artifacts on web/repositories with duplicated names (due to simplicity)?

I don't want to see in my project structure a module like project-portal-liferay-plugins-themes for parent or even worse project-portal-liferay-plugins-themes-white-puppy-wtf-name for children.

If you could provide your opinion and practice for any of mentioned questions and possible problems, that would be a great help not only for me, but and for everyone using maven. Thank you.

like image 824
JMelnik Avatar asked Feb 24 '12 17:02

JMelnik


People also ask

How do you name a groupId and artifactId in Maven project?

A good way to determine the granularity of the groupId is to use the project structure. That is, if the current project is a multiple module project, it should append a new identifier to the parent's groupId. artifactId is the name of the jar without version.

What should be the groupId and artifactId in Maven?

Maven uses a set of identifiers, also called coordinates, to uniquely identify a project and specify how the project artifact should be packaged: groupId – a unique base name of the company or group that created the project. artifactId – a unique name of the project. version – a version of the project.

How do I name a Maven module?

First of all, the most important things is that you are consistent. General Maven convention uses '-' as the separator ( commons-lang , maven-model ). If you intend for it to be used externally, remember the module = artifact ID = filename (in best practice), so it needs to be recognisable ( maven-model-2.0.

What should be the artifactId in Maven?

artifactId is the name of the jar without version. If you created it, then you can choose whatever name you want with lowercase letters and no strange symbols. If it's a third party jar, you have to take the name of the jar as it's distributed.


2 Answers

In earlier days with maven I followed the following structure which you have described:

appname   +--- appname-module1   +--- appname-module2               +--- appname-module2-chhild1               +--- appname-module2-chhild2   +--- appname-module3 

But this will become ridiculous if you get more levels.

So I decided to change my mind and now using things like:

appname   +--- module1   +--- module2           +--- chhild1                  +--- subchild1           +--- chhild2   +--- module3 

The only thing which I change through the levels is the groupId...

appname (groupId: com.soebes.appname)   +--- module1 (groupId: com.soebes.appname.module1)   +--- module2 (groupId: com.soebes.appname.module2)           +--- chhild1 (groupId: com.soebes.appname.module1.child1)           +--- chhild2 (groupId: com.soebes.appname.module1.child2)   +--- module3 (groupId: com.soebes.appname.module3) 
like image 148
khmarbaise Avatar answered Sep 19 '22 22:09

khmarbaise


I don't think there are conventions that would clearly specify on how you should setup your project structure in this case.

E.g. I would try to answer where the artifacts end up with their name and whats the chance of running into a conflict. For a framework like spring it does make sense to have the project name in the artifactId ("spring-*"), same is true for commons- libraries (although "commons-logging" may by a risky name).

For a project that runs standalone I is probably not necessary to do this. But it looks like you will use a liferay portal where a lot of different jars will be around so I would encourage a prefix for the artifacts. But I would not try to rebuild the project structure based on artifactId's. So "project-modulename" will be a good module name. Since the jars will build the classpath and the dependency structure was defined during the build this is not an issue. If you need to rebuild the dependency tree based on a list of jars: maven includes information in META-INF (if you use the release-plugin, which I also recommend) so the information can be retrieved from there.

I would also recommend to not nest modules to deeply. Eclipse has some issues with this (IntelliJ does not, Netbeans afaik supports nested structures too).

The main portal module may not change that often compared to the plugin modules. So I makes sense to split them into separate projects - this would also allow to release the projects separatly.

For me it is a good practice to name parent modules with "-parent" suffix. These modules are rarely used as dependency and a "-parent" for a dependency would indicate something is suspicious. As you said: artifacId and module name should be the same. I would also recommend using the artifactId as name in the pom. Some plugins dont consider differences here and also Eclipse behaves better if these values are all the same.

It is true the goupId and the artifactId often contain duplicate information (e.g. parts of it will be the projectname). If this was done on purpose or happend in the last years...? I dont know but I would keep it this way. Artifacts are identified using the GAV(P) coordinates (groupId, artifactId, version, (packaging)). If groupId or artifactId contain the projectname artifacts are more easy to find if you only have one of them.

Finding artifacts is easy if you are running a repository manager (like Nexus, Artifactory, Archiva). The search will often render groupId/artifactId and so on so a search for "util" would give you enough information to find the artifact you are looking for.

hope this helped a bit :) regards

wemu

like image 36
wemu Avatar answered Sep 19 '22 22:09

wemu