How to setup maven framework top level pom - maven-2

I just finished converting one of our in-house framework projects from ant to maven. The maven build runs fine, and deploys to our repository with no issues.
The problem is when other projects try to consume the framework, it does not work. The only thing downloaded is top level framework pom.
I have tried adding some dependency entries to one or more of the various modules, but no matter which one I add, I get a circular dependency error. I also tried creating a 2nd top level pom file with no modules and a few dependencies to overwrite the one in the repository manager. This causes some of the dependencies to be downloaded, but then the maven build will hang in random places. based on windows task manager, it looks like its in an endless loop. So a 2nd pom file does not appear to be the answer (or im doing it wrong).
my framework pom file looks something like this:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>framework_snt</groupId>
<artifactId>SFP</artifactId>
<packaging>pom</packaging>
<name>SFP framework</name>
<version>6.3</version>
<modules>
.... 50+ modules here
</modules>
and then the usual properties, dependency management and pluginManagement entries for a top level pom.
in the consuming module I just have the following:
<dependency>
<groupId>framework_snt</groupId>
<artifactId>SFP</artifactId>
<version>6.3</version>
<type>pom</type>
</dependency>
This is in the top level pom so all submodules have access to the framework libraries to make it easier on the developers.
How do I set things up so so all the dependent jar files will be downloaded by my consuming projects ?

It sounds like your framework project produces several jar artifacts, one for each child module, but no jar artifact for the parent project. Thus, declaring a dependency on the parent project's pom is not what you want to do. Instead you need to declare a dependency on each of your framework project's child modules.
I have a similar setup where I have a "toolkit" project with several modules (each producing a jar artifact). Then in my other projects I declare dependencies on whatever modules I need to use. I do not, however, declare a dependency on my "toolkit" parent projects pom file. Instead I just declare dependencies on the child modules jar artifacts.
<dependency>
<groupId>com.mycompany.toolkits</groupId>
<artifactId>file-utils</artifactId>
<version>1.0.0</version>
</dependency>
Notice that my dependency declaration points to one of my child module's and does not declare <type>pom</type> like you did. If you wanted to be really explicit you could declare <type>jar</type> instead.

The framework pom as you call it is the parent pom of your multi-module project.
While the modules can depend on each other, it cannot depend on this parent pom. This is what is possibly causing the circular dependency.
You will need to relook at your modules and identify which modules depend on which and suitably specify the dependencies. Also, these dependencies are typically jar dependencies - a packaging which will contain sources and resources.
Maven By Example is one of the many resources available which gives further information.

Related

How to use classes of a maven project (packaging -> maven-plugin) in another maven project (packaging -> jar)

I have created a maven plugin. I have some classes in the plugin, which I want to make available to the plugin client after execution.
The problem is that a project of type maven-plugin is also a jar, so I simply can't use maven-jar-plugin and maven-install-plugin to install the jar (having the classes) as a dependency.
Any ideas on how to do this?
I have created a maven plugin. I have some classes in the plugin, which I want to make available to the plugin client after execution.
I see two options:
declare a dependency on the plugin in the client:
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<type>maven-plugin</type>
</dependency>
put the shared classes in a shared module (with a packaging of type jar) and declare a dependency on this shared module in both the client and the plugin.
Personally, I find the second option cleaner (and you won't get all the transitive dependencies of the plugin on the classpath).

Using Maven, how can I assemble several modules into one artifact?

We have a mother-ship project with several modules:
foo
+ foo-core
+ foo-resource
+ foo-util
+ foo-whatever
I want to allow developers to include the core, resource, and util modules as dependencies (excluding the -whatever module). I know that I can specify that they include each dependency, but it would be nice to allow for them to just specify something like
<artifactId>foo-sdk</artifactId>
And get everything that they need to develop a foo. This has the added advantage that it gives us the power to add (or remove) what goes into the sdk.
It would be best if foo-sdk was not just a jar with the other jars jammed in it. I'd rather it be a pom that simply points to the other artifacts.
I feel like I've seen this done before but can't find instructions to do it. I checked out Maven Assembly Plugin but it doesn't look like this is its intended use.
You can group dependencies in a project with a packaging of type pom. From the Maven book:
3.6.1. Grouping Dependencies
If you have a set of dependencies
which are logically grouped together.
You can create a project with pom
packaging that groups dependencies
together. For example, let's assume
that your application uses Hibernate,
a popular Object-Relational mapping
framework. Every project which uses
Hibernate might also have a dependency
on the Spring Framework and a MySQL
JDBC driver. Instead of having to
include these dependencies in every
project that uses Hibernate, Spring,
and MySQL you could create a special
POM that does nothing more than
declare a set of common dependencies.
You could create a project called
persistence-deps (short for
Persistence Dependencies), and have
every project that needs to do
persistence depend on this convenience
project:
Example 3.11. Consolidating Dependencies in a Single POM Project
<project>
<groupId>org.sonatype.mavenbook</groupId>
<artifactId>persistence-deps</artifactId>
<version>1.0</version>
<packaging>pom</packaging>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate</artifactId>
<version>${hibernateVersion}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-annotations</artifactId>
<version>${hibernateAnnotationsVersion}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-hibernate3</artifactId>
<version>${springVersion}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysqlVersion}</version>
</dependency>
</dependencies>
<properties>
<mysqlVersion>(5.1,)</mysqlVersion>
<springVersion>(2.0.6,)</springVersion>
<hibernateVersion>3.2.5.ga</hibernateVersion>
<hibernateAnnotationsVersion>3.3.0.ga</hibernateAnnotationsVersion>
</properties>
</project>
If you create this project in a
directory named persistence-deps, all
you need to do is create this
pom.xml and run mvn install. Since
the packaging type is pom, this POM
is installed in your local repository.
You can now add this project as a
dependency and all of its dependencies
will be added as transitive
dependencies to your project. When you
declare a dependency on this
persistence-deps project, don't
forget to specify the dependency type
as pom.
Example 3.12. Declaring a Dependency on a POM
<project>
<description>This is a project requiring JDBC</description>
...
<dependencies>
...
<dependency>
<groupId>org.sonatype.mavenbook</groupId>
<artifactId>persistence-deps</artifactId>
<version>1.0</version>
<type>pom</type>
</dependency>
</dependencies>
</project>
If you later decide to switch to a
different JDBC driver (for example,
JTDS), just replace the dependencies
in the persistence-deps project to use
net.sourceforge.jtds:jtds instead of
mysql:mysql-java-connector and update
the version number. All projects
depending on persistence-deps will use
JTDS if they decide to update to the
newer version. Consolidating related
dependencies is a good way to cut down
on the length of pom.xml files that
start having to depend on a large
number of dependencies. If you need to
share a large number of dependencies
between projects, you could also just
establish parent-child relationships
between projects and refactor all
common dependencies to the parent
project, but the disadvantage of the
parent-child approach is that a
project can have only one parent.
Sometimes it makes more sense to group
similar dependencies together and
reference a pom dependency. This way,
your project can reference as many of
these consolidated dependency POMs as
it needs. Note
Maven uses the depth of a dependency
in the tree when resolving conflicts
using a nearest-wins approach. Using
the dependency grouping technique
above pushes those dependencies one
level down in the tree. Keep this in
mind when choosing between grouping in
a pom or using dependencyManagement
in a parent POM
Wouldn't this just be another sub-module foo-sdk with packaging pom and dependencies on foo-{core,resource,util}?

Is it possible to split maven pom files?

Is it possible to include several smaller pom files to create the parent pom file. (e.g. I would like to split the reporting, build sections into their own poms and include them in the parent pom) for managing them effectively
If you are using Maven 2, you can simply create several parent levels. The first pom.xml (pom1) will define the basic properties (such as repositories for example). The second pom.xml (pom2), which has pom1 as <parent>, will define the reporting information. And so on... Finally, the "real" pom.xml will inherit from the pom2 and will define its own properties.
You can create as many parent levels as you want (of course, it will be harder to maintain if you have 5 parent levels).
Note that Maven 3 talked about introducing the mixin concept, which will allow you to fragment your pom.xml into several files, but it looks like that is not happening now until maven 4
Not quite. You can't include reporting and build sections defined in smaller POMs, you can only inherit them from a parent POM.
If your POM is getting too large, it is possible (and recommended) to arrange your dependencies into logical groups. For example, for a GWT project, you could create a new POM for all of your persistence related to GWT as follows:
<project>
<groupId>org.yourcompany</groupId>
<artifactId>gwt-dependencies</artifactId>
<version>1.0</version>
<packaging>pom</packaging>
<dependencies>
<dependency>
<groupId>com.google</groupId>
<artifactId>gwt-user</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>org.extjs</groupId>
<artifactId>gxt</artifactId>
<version>2.1.0</version>
</dependency>
<!-- etc -->
</dependencies>
</project>
These groups can then be included in your main POM.
More recently, the option of using Maven Tiles has become possible. The plugin will allow you to perform the mixin operations not provided by Maven 3. However, each mixin requires a released tile artefact.

Activate profile in depended-on POM?

My company writes companion products for project management software that uses that software's Java API. They release new API versions with new releases of their products, and also point releases for bug fixes etc. We need to support clients using various versions of their software (and by extension, their API). In order to do this without unnecessary code duplication, we have defined profiles in our products that include the necessary dependencies for each API version.
I have a war project built using this technique with the "api70" profile activated, and another project that depends on that war project with a type of pom, in order to pull in the war's dependencies. The problem is that when building this second project, the profile-specific dependencies are not being included, even though I'm defining -Papi70 on the maven command line when building the depending project.
Is there any way to get this to work?
In the war project:
<!-- API 7.0 profile. -->
<profile>
<id>api70</id>
<dependencies>
<dependency>
<groupId>com.bigcompany</groupId>
<artifactId>integrationlibrary</artifactId>
<version>7.0-a</version>
</dependency>
</dependencies>
<properties>
<apiversion>api70</apiversion>
</properties>
</profile>
In the depending project:
<!-- Depend on war as type=pom for dependency mediation. -->
<dependency>
<groupId>com.mycompany</groupId>
<artifactId>warproject</artifactId>
<version>${warVersion}</version>
<type>pom</type>
</dependency>
Command line used for building depending project:
mvn -P api70 clean package
The resulting build does not include integrationlibrary or any of its transitive dependencies.
I think that your problem doesn't apply to profiles at all. It's about how transitive dependencies work for war packaging. By design they doesn't work :) War archive contain its dependencies in WEB-INF/lib folder or if it is packaged in ear it can share libraries with ear libs. More of the problem you can read on this wiki article. It's about Skinny Wars but topic relates also your problem.
For you interesting is also this JIRA issue.
Quick but not elegant solution is to change packaging form war to pom (or create duplicate pom with pom packaging).
Why don't you create an api70-deps pom project and let your war and dependant project both pull that in, profile activated or otherwise?
This approach works wonders for me... my poms become so much more tidier.

Maven - add dependency on artifact source

I have two maven modules, one that ends up as a jar, and one war that depends on that jar.
I want the jar module to package it's source code together with the compiled classes in the jar, so that the second module is able to access it. I have tried using the maven-source-plugin, but I am confused as to how to add a dependency on the output of that. It seems that the dependency by default goes to the compiled jar, and not the source-code jar (ending with "-source.jar") that maven-source-plugin creates.
How do I add the "-source.jar" as a dependency, while still preserving the dependency on the compiled sources?
I've not tried this, but I think you need to create two profiles in your project. One which builds the main jar. The other which builds the sources jar. Unfortunately, I'm not exactly sure how you would build that profile. I couldn't find a good example of it so far.
(Accoding to the comments, you don't actually need a profile. You can just use the sources-plugin which will deploy the sources and make them available via the sources classifier)
In theory, you'd use the 2nd profile to attach the sources to the project. This creates a 2nd entry in your repository for the sources using that classifier. Once you install/deploy the sources to your repository, you should be able to include the sources as a dependency by using the classifier tag on the dependency to specify the sources directly.
So you'd have something like this in your webapp POM:
<dependencies>
<dependency>
<groupId>myGroup</groupId>
<artifactId>myJar</artifactId>
<version>4.0</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>myGroup</groupId>
<artifactId>myJar</artifactId>
<version>4.0</version>
<type>jar</type>
<classifier>sources</classifier>
</dependency>
</dependencies>
Did you try adding the src directory as a resource directory in the build section? That should copy the source into the jar on build.