Reputation: 866
I am developing a number of projects (currently organized as eclipse projects). There is a core project which mainly provides the core API and some secondary implementations and abstract classes. All other projects depend on this project.
When integrating the projects into our maven repository, we got problems with the maven naming conventions. As discussed on SO, the groupId should usually be the reverse company domain name (com.example
) plus the project name (com.example.foo
). The maven naming conventions suggest an additional postfix for sub-projects such as plugins (com.example.foo.plugin
).
In our case, we have not got plugins, but multiple (mostly independent) implementations of the API provided by the core project. Our current naming suggestion is:
com.example.foo
as the groupId of all projects, although they are split up into different java packages (com.example.foo
contains the API, com.example.foo.bar
contains the bar
implementation)bar
instead of foo-bar
)The key point is that (although our projects are spread accross packages as described above) they are not really sub-projects of the API core project.
Does this suggestion comply with the maven naming conventions?
Just in case: This question is not asking for opiniated responses but for an argumentative answer to the above question.
Upvotes: 8
Views: 4391
Reputation: 21316
I just want to add a comment regarding naming conventions for the parent POM. Several responses, including the answer by carlspring and the answer by by Steve K, indicated naming the parent pom simply parent
:
com.example.foo:parent
com.example.foo:foo
com.example.foo:foo-bar
com.example.foo:foo-bat
com.example.foo:foo-baz
I completely agree with the sentiment, because the parent POM is not a sub-module, which is what foo-parent
would seem to imply.
Option 1: com.example.foo:parent
There is however a big problem using simply parent
as the artifact ID, besides the fact that it doesn't give much info when searching for it in the Maven Repository. If you import the project into Eclipse, the IDE will use parent
for the project name!! This is unsightly, and trying to import two projects that use this convention will cause pain.
But I also don't want to name the artifact foo-parent
, because as I mentioned it's not a submodule. Additionally, it will likely be sorted in the middle of the submodules, making it hard to find it in my IDE.
Option 2: com.example.foo:foo-.parent
After much thought and experimentation, I decided I'd like to propose a convention for parent POM artifact IDs: project-.parent
. (Yes, this identifier is allowed by Maven.) This shows that the artifact is part of "project", but by beginning with a .
it shows that it is a special POM, sort of like a metadata file or a configuration directory. Plus it sorts it to the front of the modules (although not in front of the single project
artifact ID). So the module coordinates would look like this:
com.example.foo:foo
com.example.foo:foo-.parent
com.example.foo:foo-bar
com.example.foo:foo-bat
com.example.foo:foo-baz
There's a drawback, though: many tools don't seem to support thing. It looks like having dots in the artifact ID causes issues with JitPack, JFrog Artifactory, and OSGi Bnd, for example.
Option 3: com.example.foo:foo--parent
I then thought about using foo--parent
, or even just foo--
. But as -
is used as semantically a component separator within the artifact ID, I was worried that a tool might hiccup if two dashes were next to each other. Plus adding a version to the end of the artifact (e.g. foo---1.0.0.jar
) would look a little odd.
Option 4: com.example.foo:foo_
Then I stumbled across a blog entry that pointed out that Eclipse has an option for viewing projects hierarchically!! I suddenly realized that my main issue was with a specific use case: that where the aggregate POM is the same as the parent POM, and the main project artifact is in the subdirectory. For example, in repository foo
, the project is found inside foo/foo
, so what do I name the aggregate POM artifact ID?
Suddenly sorting wasn't such a big deal anymore, because Eclipse would show the root project in a tree.
foo-parent
.foo
.So the remaining problem is for a project like this:
…/foo/pom.xml #com.example.foo:???
…/foo/foo/pom.xml #com.example.foo:foo
…/foo/foo-bar/pom.xml #com.example.foo:foo-bar
…/foo/foo-bat/pom.xml #com.example.foo:foo-bat
…/foo/foo-baz/pom.xml #com.example.foo:foo-baz
I would like to give it an artifact ID of foo
, but I can't do that as the main foo
artifact is in a subdirectory. So for this special case, I'm leaning towards foo_
.
…/foo/pom.xml #com.example.foo:foo_
…/foo/foo/pom.xml #com.example.foo:foo
…/foo/foo-bar/pom.xml #com.example.foo:foo-bar
…/foo/foo-bat/pom.xml #com.example.foo:foo-bat
…/foo/foo-baz/pom.xml #com.example.foo:foo-baz
This shows up as foo_
at the root of the tree in Eclipse, and there is not much chance a tool will have problems with a trailing underscore (at least less of a chance than a dot or duplicated dashes).
I'd be interested to get feedback on this discussion and my (current) conclusion.
Upvotes: 0
Reputation: 5916
I'd say it's okay to have all your artifacts in the same groupId. But you should use the sub project pattern where appropriate.
For example, Spring has all its main artifacts in one groupId, org.springframework. That includes the core of spring and the JMS, ORM and WMV subprojects. But then bigger sub-projects like Spring Boot have a separate groupId, org.springframework.boot. I would say this is a good pattern to follow.
Upvotes: 1
Reputation: 32567
I would say this is a matter of your own taste and preference.
Normally, you would group similar sets of modules under the same groupId
. For example, you could have the following:
com.foo.bar:parent (parent pom for all projects)
com.foo.bar:core-api (some very core classes)
com.foo.bar:commons (some common classes)
com.foo.bar:io (some IO classes)
com.foo.bar:utils (some utility classes)
com.foo.bar.messaging:messaging-core (messaging core classes)
com.foo.bar.messaging:messaging-rest-api (REST API for messaging)
com.foo.bar.messaging:messaging-jms (some JMS code)
com.foo.bar.web:rest-api (your restlets)
com.foo.bar.web:web-core (core classes to be used by web modules)
com.foo.bar.web:web-parent (a parent pom for all your web projects)
com.foo.bar.web:web-ui (UI stuff like css/images/js/etc)
com.foo.bar.web:web-assembly (a web assembly that bundles all modules)
... (I hope by now you get my drift) ...
You don't necessarily need to group all modules whose classes start with a common package under the same groupId
. You could do that, if you like, but that's rarely how people really use it in real life. The level of strictness and magnitude of detail is up to you, but in the case of artifacts, it usually doesn't matter that much as there's nothing to tie the package name to the groupId
.
Furthermore, using a prefix for your modules is also helpful, but up to you. If you like, you could have:
com.foo.bar:bar-parent
com.foo.bar:bar-core-api
com.foo.bar:bar-commons
This is really up to you. Some will argue that if you have a groupId
like com.foo.bar
, then you don't need to have a bar-
prefix in bar-parent
. To some extent this is true. But then you could have com.foo.bar:parent
and com.foo.bar.web:parent
and when you're using a repository manager like Nexus, Archiva or Artifactory and you're searching for parent
, (or some other common name like... commons
, for example), you might end up with a rather long list of results, as opposed to bar-parent
.
In the end, what matters is to what level of detail you're willing to go and what will really suit your needs. Maven allows you all the freedom you need in this regard.
Upvotes: 12
Reputation: 4921
The naming of things is really important, and the names should convey important information right away. For this reason, the conventions my company have used state that group Id should be the same for all implementations of a specific thing: each one's group Id is com.example.foo, because they're all implementations of that. The project names should refer to the interface, and hyphenated with the name for their particular implementation, with the main parent pom labeled prominently as 'parent':
com.example.foo:parent
com.example.foo:foo-bar
com.example.foo:foo-bat
com.example.foo:foo-baz
This way, you can tell at a glance from the names exactly how these things are related, and the artifact names also individually denote that they are different types of foo. This also means that imports in the java code follow exactly the same structure. It also makes imports very legible and understandable in the java code as well.
Upvotes: 2
Reputation: 21186
So as I see it you have a bunch of options which follow maven naming conventions...
Foo refers to the core API and bar refers to the implementation.
com.example.foo (referring to the core api) as the group and then the implementation being foo-bar (convention says you include a hook back to the group in your artifact name).
com.example.bar as thr group and the artifact id is bar-impl or some other appropriate suffix
com.example.foo.bar as the group and bar-impl or some other appropriate suffix.
For 1 you are saying to the unfamiliar: the implementation is closely coupled to the API and has a closely related release cycle. When a new versio of the core API is released a version of the implementation is also released. Furthermore the implementation is a child of the core API and does not really stand alone. You are also saying the core business of bar is to be an implementation of bar and has little value apart from it (it doens't do much else).
In 2 you are saying the implementation of the core API does have it's own lifecycle and generally is not released on the same cycle as the API. Furthermore it is not a sub project of the core API and can thus stand alone. In other words, it's core business and usage is not only as an implentation of foo. If bar can have siblings this is especially attractive.
3 is a middle road between the two. It says bar has value by itself as well as having significance as an implementation of foo and also potentially allows for siblings. It slightly improves on 2 as it does provide some feedback that this artifact is an implementation of foo. Again, if bar can have siblings this makes more sense.
So I guess you'd need to select where your implementations of the API sit. The biggest driver is probably whether bar can have siblings.
Upvotes: 3