Is it possible to specify multiple main class in pom file? - maven

I am using Spring-boot to develop an application. The reason I need to specify multiple main classes is that, my program runs as a 'tool'. By starting with different main classes, I can finish tasks. I currently specify one main class in this way:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<configuration>
<mainClass>com.lu.qe.ClassificationService</mainClass>
</configuration>
</plugin>
Then I can start my application by running at a terminal:
mvn spring-boot:run
This only runs the "ClassificationService" main class. I also want to be able to possibly run another main class, like "ClassificationService_2". In such a case, how to achieve this? Is it possible to let 'mvn spring-boot:run' take a parameter?

From command line argument main class can be pass but it will fail to run because multiple main class will be found..
mvn spring-boot:run -Dloader.main=DemoApplication
But I think you can manage it by defining multiple profiles and then in command line you can pass profile argument..not checked but should work.
<profiles>
<profile>
<id>profile1</id>
<properties>
<spring.boot.mainclass>com.MainClass1</spring.boot.mainclass>
</properties>
</profile>
<profile>
<id>profile2</id>
<properties>
<spring.boot.mainclass>com.MainClass2</spring.boot.mainclass>
</properties>
</profile>
</profiles>

I'm also developing a 'tool' that requires multiple main classes. springboot does not support this demand but I found maven parent pom feature exactly satisfy my requirement.
step 1 - to change a pom.xml to a parent pom, change the packaging type to 'pom', a parent pom looks like this:
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
step 2 - create another pom file let's say service1.xml, and set this, pay attention to the relativePath element:
<parent>
<groupId>com.example</groupId>
<artifactId>test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>./pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>service1</artifactId>
<version>0.0.1-SNAPSHOT</version>
step3 - then you can specify the pom file when run a mvn command
mvn -f service1.xml spring-boot:run
mvn -f service1.xml clean package

Related

mvn exec works, but Run 'Application' does not

I have a simple maven project using Micronaut. I'm trying to create a new module and make the typical 'WelcomeController', and communicate that module with the parent pom.
I can run it command-line via mvn exec:exec but running it with the IDE (IntelliJ IDEA) doesn't work for me. I got the following error:
Error: Could not find or load main class com.example.Application
Caused by: java.lang.ClassNotFoundException: com.example.Application
Child pom:
<parent>
<groupId>com.example.reports</groupId>
<artifactId>tnt-assignment-back</artifactId>
<version>0.1</version>
</parent>
<artifactId>tnt-rest</artifactId>
<description>Rest module for tnt-assignment</description>
<properties>
<exec.mainClass>com.example.reports.Application</exec.mainClass>
</properties>
Parent pom:
<parent>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-parent</artifactId>
<version>2.2.1</version>
</parent>
<groupId>com.example.reports</groupId>
<artifactId>tnt-assignment-back</artifactId>
<version>0.1</version>
<packaging>pom</packaging>
<modules>
<module>tnt-rest</module>
</modules>
Any ideas? I've tried many things but still don't go. Thanks.
It looks like you are trying to run com.example.Application from the IDE and maven is configured to run com.example.reports.Application.

Deploy Two Wars to a Repository with One Pom

I have a single project that builds two war files. The only difference between the two are configuration files and the war name. I'm trying to deploy the wars to our Nexus repository for distribution management. I know how to name the wars differently in the pom by using:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>example</artifactId>
<version>1.1.2</version>
<packaging>war</packaging>
<properties>
<buildVersion>counter</buildVersion>
</properties>
<build>
<finalName>example_${buildVersion}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
</plugin>
</plugins>
</build>
<distributionManagement>
<repository>
<id>nexus.example</id>
<url>https://example.com/nexus/content/repositories/wars</url>
</repository>
</distributionManagement></project>
But, when I run mvn deploy, the name of the war that is deployed doesn't have the buildVersion so both wars are named the same.
I've found the deploy:deploy-file directive, but it needs the version of the war that's being deployed defined as a -D spec. Since I'm doing CD, I don't have the version on the command line within Bamboo.
Has anyone come across this situation before and what was done to accomplish it?

Running multiple Maven instances of a framework, how to set the goals?

Framework is run from a root directory typing
mvn ninja:run
To run two or more instances of Maven, I have to use modules. I got that part as:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.maventest</groupId>
<artifactId>myproject</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<name>myproject</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<modules>
<module>/user</module>
<module>/admin</module>
</modules>
</project>
To run on a specified port, I would have to type
mvn ninja:run -Dninja.port=YourPortNumber
what changes do I need to add to a pom.xml file and where, to get the both instances running at the same time and on different ports?
Edit: Ideal solution would be typing just a simple "mvn" command to start the modules which would make both instance run.
According to the documentation of the Ninja Plugin, you can configure the port as part of the plugin configuration as well, not only via command line option (the -Dninja.port=YourPortNumber option you mentioned).
Hence, in your two sub-modules, you could configure the plugin as following:
<build>
<plugins>
<plugin>
<groupId>org.ninjaframework</groupId>
<artifactId>ninja-maven-plugin</artifactId>
<version>5.2.2</version>
<configuration>
<port>1234</port>
</configuration>
</plugin>
</plugins>
</build>
As part of the port section, you can then type in each of the sub-module the specific port number you want to use and not providing it anymore from the command line. Also note, in the snippet above I used the 5.2.2 version (the latest), but you can change it according to the version you meant to use. Further note: you may already have a build section as part of your POM, in that case you would only need to add the plugin section above to the existing list of plugins configurations, if any.
As such, you would only require to execute mvn ninja:run, port numbers will be provided by each sub-module configuration.
Side note: it should be clear that Maven is a build tool and not an executor tool (even though it is a plugin executor in its bones), so we cannot pretend to simply launch mvn and execute our own logic.

Retaining module keys when migrating Sonar from Maven runner to Ant runner

We'd like to convert our existing multi-module Sonar projects that use the Maven runner to use the Ant runner instead. These projects all use Ant for their main build anyway, and it will be a lot more convenient to have everything done with Ant.
We must preserve the history of the projects, meaning that we need to retain the keys used for the projects and their modules. I'm having trouble doing that.
Our current Maven parent pom looks something like this (the ui is similar, though the language is Flex):
<project ...>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>anapp</artifactId>
<name>An Application</name>
<version>7.0</version>
<packaging>pom</packaging>
<modules>
<module>server</module>
<module>ui</module>
</modules>
<properties>
<sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>
</properties>
</project>
The server module pom looks like this:
<project ...>
<parent>
<groupId>com.example</groupId>
<artifactId>anapp</artifactId>
<version>7.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>anapp_server</artifactId>
<name>Server</name>
<version>7.0</version>
<build>
<outputDirectory>build/classes</outputDirectory>
<sourceDirectory>src/main/java</sourceDirectory>
<testOutputDirectory>build/test/classes</testOutputDirectory>
<testSourceDirectory>src/test</testSourceDirectory>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>
<sonar.core.codeCoveragePlugin>emma</sonar.core.codeCoveragePlugin>
<sonar.emma.reportPath>build\codecoverage-results</sonar.emma.reportPath>
<sonar.surefire.reportsPath>build\test\results</sonar.surefire.reportsPath>
</properties>
</project>
We set the sonar.branch property on the command line to "R7".
The key of the "myapp" project looks like
com.example:anapp:R7
The key of the "Server" module within the "myapp" project looks like this:
com.example:anapp_server:R7
For the same project to use the Ant task, I set up the properties as:
sonar.dynamicAnalysis=reuseReports
sonar.modules=server,ui
sonar.projectBaseDir=...
sonar.projectKey=com.example\:myapp
sonar.projectName=An Application
sonar.projectVersion=7.0
server.sonar.binaries=...
server.sonar.dynamicAnalysis=reuseReports
server.sonar.emma.reportPath=...
server.sonar.java.coveragePlugin=emma
server.sonar.java.source=1.6
server.sonar.language=java
server.sonar.libraries=...
server.sonar.projectBaseDir=...
server.sonar.projectKey=com.example\:anapp_server
server.sonar.projectName=Server
server.sonar.sources=...
server.sonar.surefire.reportsPath=...
server.sonar.tests=...
ui.sonar.dynamicAnalysis=false
ui.sonar.language=flex
ui.sonar.projectBaseDir=...
ui.sonar.projectKey=com.example\:anapp_ui
ui.sonar.projectName=UI
ui.sonar.sources=...
The key of the project looks the same as with the pom file ("com.example:anapp:R7"); however, the server module key looks like
com.example:anapp:com.example:anapp_server:R7
This difference will cause us to lose the history of the modules if I publish using them.
Is there a way for me to specify the Ant properties to generate the same key as with our existing Maven pom files?
Our Sonar admin tells me he can manually change the keys for us, but this would be tedious and time consuming. We'll resort to that if we have to, but I'm hoping I'm just missing something obvious that would save us a lot of work.
There's no way to transform Maven-style keys in standard SonarQube-style keys.
So your admin is right, the only way to do it is to manually update the keys through the interface, as explained on the documentation.

Defer properties evaluation in Maven sub-modules

I have some problems trying to run maven in a 3-level multi-module project.
The first level is the super-pom, which defines antrun tasks. It is located in an external repository.
The second one refers to the super-pom, and only include the definition of submodules. Let's say it is in /project
The third level contains the sub-module and its items are located at /project/moduleN.
At the first level, AntRun tasks includes calls to "${project.basedir}".
When I use maven, I go to the second level pom folder and run mvn clean install.
As it only includes sub-modules, it tries to compile them but ${project.basedir} has already been evaluated as being /project, and not /project/moduleN.
I would like to defer the evaluation of those expressions in order to replace them with values from my sub-modules, and not from the pom including them, but I can't find a way to do so.
Here are excerpts from POM files to understand what's going on :
Super POM
<groupId>org.example</groupId>
<artifactId>superpom</artifactId>
<packaging>pom</packaging>
...
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
...
<exec dir="${project.basedir}" ...></exec>
</plugin>
</plugins>
Project POM
<parent>
<groupId>org.example</groupId>
<artifactId>superpom</artifactId>
</parent>
<groupId>org.example</groupId>
<artifactId>projectPom</artifactId>
<packaging>pom</packaging>
<modules>
<module>module1</module>
<module>module2</module>
</modules>
Modules POM
<parent>
<groupId>org.example</groupId>
<artifactId>projectPom</artifactId>
</parent>
<groupId>org.example</groupId>
<artifactId>moduleNPom</artifactId>
<packaging>jar</packaging>

Resources