Custom pom.xml filename in Maven multimodule for Tycho - maven

I have a project with a couple of dozen Eclipse plugins, all inter-related and living in different subfolders. The build was converted to a multi-module manifest-first Tycho build a couple of years ago and it works quite well.
One of the plugins is rather key, and can also be built as a standalone Java app, which doesn't use an Eclipse runtime. Currently it has its own POM file (pom-standalone.xml) so that Jenkins can build the standalone app separately and the Tycho build knows nothing about it - the pom-standalone just lists the previously-built plugin jars (thanks Tycho!) and Eclipse libraries that it needs as dependencies. Couple problems with this approach though:
I cannot easily use IntelliJ to work on the standalone project with Maven dependency management, because it doesn't recognize the custom pom-standalone.xml filename as a POM.
The many jars that this project relies on are checked in to the project for the sake of Tycho and the Eclipse Manifest file, but they're also managed by Maven for the standalone build. So any dependencies have to be added to the pom-standalone.xml file AND entered into the OSGi manifest AND checked in to the source control for Eclipse purposes.
It seems like a straightforward workaround would be to tell Tycho/modules to use something other than pom.xml for the submodule's POM, or perhaps all the multimodule POM files, since Eclipse doesn't use those anyway - then the pom-standalone.xml can be converted to pom.xml and then IntelliJ will be fine with it.
I know you can specify the -f attribute to Maven builds, but will that really apply to all submodules? Can you specify the POM filename for just ONE submodule?
Are there alternative solutions? Eclipse/Tycho/p2 builds seem somewhat of a headache requiring manual library management and checking in libraries to source control, but maybe there have been changes I'm not aware of in the Eclipse build world the last few years.
Found a Similar Question that didn't help much.

You can include projects in an aggregator POM by specifying the full name to the POM file with custom name. Example:
<modules>
<module>org.example.bundle1</module>
<module>org.example.bundle2</module>
<module>org.example.keybundle/pom-tycho.xml</module>
</modules>
This both works in a pure Maven and Maven/Tycho build.

To extend #oberlies answer a little bit:
SCENARIO: top aggregation POM comes in multiple flavors, so any style can be built from the top.
<!-- in file pom.xml -->
<modules>
<module>org.example.bundle1</module>
<module>org.example.bundle2</module>
<module>org.example.keybundle</module>
</modules>
All submodules will be built using their standard pom.xml
and
<!-- in file pom-tycho.xml -->
<modules>
<module>org.example.bundle1/pom.xml</module>
<module>org.example.bundle2/pom.xml</module>
<module>org.example.keybundle/pom-tycho.xml</module>
</modules>
Submodules will be built using the specifically named POM file.
and, likewise:
<!-- in file pom-special.xml -->
<modules>
<module>org.example.bundle1/pom.xml</module>
<module>org.example.bundle2/pom-special.xml</module>
<module>org.example.keybundle/pom-tycho.xml</module>
</modules>
Submodules that have custom POM files use them, and others state they still want the normal POM file, all independent of the name of the top aggregation POM file.
Because mvn -f pom-tycho.xml assumes that file name in all submodules. So if you do want pom.xml in any submodule when the top file isn't named pom.xml you need to fully specify for each submodule.

Related

Intellij Spring maven install error "package does not exist"

Intellij version : Community 2019.2.3
Maven : 3.6.2
Spring : 2.2.0
I am trying to create a very simple Spring maven project with two sub-modules (one independent and another one dependent on independent one).
Root module - testmultimodule
Independent module - independent
Dependent module - dependent
testmultimodule pom.xml has all Spring related declaration and module definition
<modules>
<module>independent</module>
<module>dependant</module>
</modules>
Independent poom.xml is simplest and . only has parent maven declaration
<parent>
<artifactId>testmultimodule</artifactId>
<groupId>in.org.app</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
dependent module pom.xml has the dependency declaration as below to independent module
<dependencies>
<dependency>
<groupId>in.org.app</groupId>
<artifactId>independent</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
I have created a Test class under dependent module and using a User object from independent module. Initially, without the above dependency declaration, asa usual there was compilcation error.
As soon as I add the dependency and builld the project within Intellij IDE with the option "Build Prooject" option from "Build" menu, it successfully builds.
However, if I try to use Maven install option within Intellij right side window option. It always fails stating Error:(3,33) java: package in.org.app.independent.bo does not exist .
I am providing the GitHub URL for the test project , if you want to take a look and test by yourself.
GIT URL:
https://github.com/DhruboB/testmultimodule
I have tried all sort of tweaking found in internet so far e.g.
clearing Intellij Cache & restarting, mvn -U clean install, mvn scope verification, proxy etc.
Any further idea to resolve this? I need to solve this in the Community version of Intellij.
Your parent project includes the definition for the spring-boot-maven-plugin. This leads to each project defining this as a parent to be repacked to an executable JAR by this plugin. This repackaged JAR isn't useable as a dependency in another project.
Either you need to change the configuration of the spring-boot-maven-plugin for the project you want to use as a dependency. This is explained here in the Spring Boot Reference Guide. You now basically have 2 jars from this project, one plain and one executable.
If you don't need that project to be an executable JAR file then just move the spring-boot-maven-plugin to the project that needs to be. All other projects will no be basic JAR files again.
See also How to add a dependency to a Spring Boot Jar in another project?

Maven - import / group all modules of project

I have a parent project with around 20 child modules:
<project>
<modules>
<module>module-1</module>
<module>...</module>
<module>module-20</module>
</modules>
</project>
I would like to use this project as one single entity, with all 20 modules included, in other projects. What is the convenient way to do this in Maven?
Should I make a new child module which imports the other 20 modules and refer to this project? Should this be a JAR or a POM project?
<project>
<packaging>jar</packaging>
<dependencies>
<dependency>... module-1 ...</dependency>
<dependency>...</dependency>
<dependency>... module-20 ...</dependency>
</dependencies>
</project>
I think the way you mentioned in your question is a good idea. It is actually mentioned as a best practice in the Maven book, quoting:
If you have a set of dependencies which are logically grouped together. You can create a project with pom packaging that groups dependencies together.
You can create a new module called module-all, which would be of pom packaging, that simply has a dependency on each of the modules. The packaging should be pom because the primary artifact of this module will only be the pom.xml (there will be no sources to compile, no JAR...). Then, in your external projects, you can simply add a dependency to this new module (as <type>pom</type>) and every module-i dependencies will be included transitively.
There would be a cave-at if all of your modules did not share the same version: there would need to be a reference to a specific version of a specific module and you would have to update the module-all version each time a module's version changes. However, if they all share the same version, module-all release cycle would be in line with module-i's.

Maven multiple parent-child hierarchy

I have a project that is built in the next manner:
parent module named Production, it holds two modules named apps and libs, each of them holds various projects.
Production
apps
common
utils
libs
api
dev
Production pom
<groupId>com.prod</groupId>
<packaging>pom</packaging>
<modules>
<module>libs</module>
<module>apps</module>
</modules>
Apps pom
<parent>
<groupId>com.prod</groupId>
<artifactId>apps</artifactId>
</parent>
<modules>
<module>common</module>
<module>utild</module>
</modules>
Where packaging of Production, apps and libs is pom.
While the packaging for the rest is war/jar.
When I try to run mvn install on Production (or any other module/project) I get Non-resolvable parent POM: Failure to find
Only when I run mvn install -N on Production, apps and libs, I can finally start working with the projects.
Is there a better way to accomplish successful modules and projects alignment without running mvn install -N? some pom definition or some other solution?
Without seeing your POMs, I am guessing that you are missing <module> elements naming the children in Production, apps and libs POMs.
Once you have that, if everything else is in order, you can build from the Production folder with mvn install and have the reactor figure out what the right order to build the various modules are, subject to inter-module dependencies. Note that the <module> elements are relative paths to the child projects, not anything to do with the GAV of the project.
See http://books.sonatype.com/mvnex-book/reference/multimodule.html for more information about proper setup for multi-module projects.

about generate maven dependency

I am pretty new to maven.
Now I have a maven project developed. My another project needs to depend on this one.
Does anyone know how can I generate my own dependency? So that my second project can add the first one as a dependency in pom.
thank you very much
Since your first project is already a maven-project, just install it in your local repository by running mvn install in the first project's root directory.
Then you can include a dependency in your second project by simply referencing the groupId, artifactId and version you defined in the first project.
So if your first project had the following in its pom:
<project>
<groupId>com.yourdomain</groupId>
<artifactId>yourcomponent</artifactId>
<version>1.0</version>
... <!-- more here -->
you can include this in your second project:
<dependencies>
<dependency>
<groupId>com.yourdomain</groupId>
<artifactId>yourcomponent</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
Unless you deploy your project 1 jar to a central maven repository, this will only work if your jar is in your local repository (via mvn install).
Maven projects are identified by the "Maven coordinates", that is, the ArtifactID, GroupID and version.
Say you create your first project and run maven install. Your local repository (in $HOME/.m2/) will now contain the compiled project plus whatever coordinates you put in there.
Your second project must now only depend on the said coordinates.
I would suggest googling a bit on maven. I made a tutorial a long time ago that might help you, even if the examples are a little simple. Here you go and good luck!

Instruct Maven to use Ivy's generated classpath

We are adding new code to an existing project that uses a custom build system developed with Ant and Ivy for dependency management.
Our new team is used to Maven and its features like testing execution, cobertura reports, etc.
Our question is: is it viable to add a pom.xml matching the current project structure, but instruct Maven to load its classpath from the "lib" dir already filled by Ivy?
In other words: we want to use Maven without its dependency management.
One really dirty approach would be to generate one big jar from the libdir and config the pom.xml to include just that... but we believe there should be cleaner approach.
Any idea or recommendation?
Note: we are not interested in generating a pom.xml with dependencies from the Ivy config, we just want Maven to rely on Ivy's generated classpath. No need to discriminate between test/runtime/compile classpath.
This is our final setup to solve this:
For each Ivy legacy project, use ivy:makepom and manual inspection to figure out the dependencies that we need to send to the new projects (Maven-based). This is a one-time process for each project.
Modify the legacy build system in a way that, every time a project is built, the identified dependencies are also exported to a mvn repo. Because de build machine holds the internal repo, we just use mvn install.
In the new maven projects, declare each dependency in the pom.xml and make sure the build system runs maven builds after the legacy builds.
Thank you all for your help!
One possibility is to use the system scope to define your dependencies in maven. This allows maven to use the jars downloaded by ivy for its dependencies.
e.g.
<dependencies>
<dependency>
<groupId>group.id</groupId>
<artifactId>artifact</artifactId>
<version>a.b.c</version>
<scope>system</scope>
<systemPath>${basedir}/lib/artifact-a.b.c.jar</systemPath>
</dependency>
...
</dependencies>
Maybe the makepom task will be helpful, it creates a pom from the ivy file.
Example from that page:
<ivy:makepom ivyfile="${basedir}/path/to/ivy.xml" pomfile="${basedir}/path/to/module.pom" conf="default,runtime">
<mapping conf="default" scope="compile"/>
<mapping conf="runtime" scope="runtime"/>
<dependency group="com.acme" artifact="acme-logging" version="1.0" optional="true"/>
</ivy:makepom>

Resources