How to create a private JAR in a local subdirectory which I have designated as an additional repository? - maven

In a subdirectory under a project, I have a library module of code I write and maintain that must be shared with other modules in the larger project. For convenience, it's developed simultaneously alongside all the modules consuming it.
project
libs
module-A
module-B
module-N
library-module
For complicated reasons imposed by how our build is done after it leaves our hands, we don't want it deployed to the build host's local Maven repository (~/.m2/repository). Instead, we want it in a subdirectory local to the project, here libs.
From the command line, I know the following will put it into the local Maven repository, but I don't want to do this from the command line and I don't want the result to go to the local Maven repository. I want this to happen when mvn install is run by the build system in the library-module subdirectory.
mvn install:install-file -Dfile=your-artifact-1.0.jar \
[-DpomFile=your-pom.xml] \
[-Dsources=src.jar] \
[-Djavadoc=apidocs.jar] \
[-DgroupId=org.some.group] \
[-DartifactId=your-artifact] \
[-Dversion=1.0] \
[-Dpackaging=jar] \
[-Dclassifier=sources] \
[-DgeneratePom=true] \
[-DcreateChecksum=true]
(Note that the answer I'm looking for would not be IDE-dependent.)

To meet the provided requirements, two configuration steps are then required:
Disable the default artifact installation to the local repository, via the skip option of the Maven Install Plugin
Configure the install-file goal within the POM in order to have it as part of your build (hence no need to invoke it manually from command line)
The following configuration would provide it:
<properties>
<library.repository.folder>../libs</library.repository.folder>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
<configuration>
<skip>true</skip>
</configuration>
<executions>
<execution>
<id>install-artifact</id>
<phase>install</phase>
<goals>
<goal>install-file</goal>
</goals>
<configuration>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${project.version}</version>
<packaging>${project.packaging}</packaging>
<file>${project.build.directory}/${project.build.finalName}.${project.packaging}</file>
<localRepositoryPath>${library.repository.folder}</localRepositoryPath>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Please note the library.repository.folder property used to point to the desired target lib folder (to change in case of different path). The configuration provided above makes use of standard maven properties (for project coordinates and packaging), but you can change them (or hard-code real values) as required.
Also note that the install-file goal will recreate under the lib folder the same folders structure as in the local repository (lib\groupId\artifactId\version\file.jar). If you instead would like to have the file straight under the lib folder (lib\file.jar) you could then move to the following configuration:
<properties>
<library.repository.folder>../libs</library.repository.folder>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.6</version>
<configuration>
<outputDirectory>${library.repository.folder}</outputDirectory>
</configuration>
</plugin>
</plugins>
</build>
This time we are not using the install-file goal but rather the jar goal of the Maven Jar Plugin to place the packaged artifact directly to the lib folder (instead of the standard target folder) and during the package phase (not install).
If by any reason you want to keep the final artifact in the target folder AND have it straight copied to the lib folder (no maven folders hierarchy) AND during the install phase, then you could move to the following configuration:
<properties>
<library.repository.folder>../libs</library.repository.folder>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>re-package-into-lib</id>
<phase>install</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<outputDirectory>${library.repository.folder}</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

Related

is it possible to version and deploy a configuration file to nexus via maven commands

I am working on a java project and I would like to version and store a configuration file on nexus. Lets assume the file structure of java project is as below.
src/
conf/application.config
pom.xml
Is it possible to deploy application.config file to nexus when I run mvn clean install. After each build I expect an application artifact and a configuration artifact to be deployed to nexus. Is there any maven plugin for this purpose.
I manged to deploy file with maven-deploy-plugin.
http://maven.apache.org/plugins/maven-deploy-plugin/usage.html
You can find an example below.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
<executions>
<execution>
<id>deploy-file</id>
<!-- change to deploy-->
<phase>install</phase>
<goals>
<goal>deploy-file</goal>
</goals>
</execution>
</executions>
<configuration>
<file>app.properties</file>
<repositoryId>stack.example.release</repositoryId>
<url>http://nexusserver/nexus/content/repositories/releases/</url>
<groupId>com.stack.example.config</groupId>
<artifactId>app</artifactId>
<packaging>properties</packaging>
<version>1.0.0</version>
</configuration>
</plugin>
</plugins>
</build>

How to maintain daily SNAPSHOT build using TeamCity in C# projects

I am taking over a project which consists of around 15 projects, whose continuous integration practice was done (the practice was ceased and I need to re-start it in a new environment) by Maven + Nexus OSS + TeamCity and are developed using C#.
What I got, except for those C# solutions themselves, is a POM for each of these project, and another parent POM (which doesn't contain any code) which every other project has parent of. These development POMs only have inter-dependency on SNAPSHOT versions hence the build order is crucial. But these POMs that I have do not need any VS plugin, which means (I guess) the compile procedure is not done by Maven but by TeamCity (VS runner). The Maven scripts I have are probably only in charge of e.g., downloading dependencies, validating and installing/deploying/releasing. Unfortunately I can't find any TeamCity configurations so I have no clue how this was done before.
EDIT:
I'll try to put some POM and script file that I have and see if someone can see some clue on the build procedure.
The files I got from SVN are mainly in three kinds categories:
1) The C# source code and project/solution files. Each solution has a 'Dependency' folder which contains all the dependencies, both on other projects on third-party dlls, so that this solution can be built in VS by the developer right after he checkout this solution.
2) The (development) POMs.
Firstly I have the POM of the parent project. This project doesn't contain any code but only the POM and some scripts (other projects have similar files too). The POM looks like this:
<modelVersion>4.0.0</modelVersion>
<groupId>MY.GROUP</groupId>
<artifactId>configuration</artifactId>
<version>1.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Configuration</name>
...
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.8</version>
<executions>
<execution>
<id>purge-local-dependencies</id>
<phase>clean</phase>
<goals>
<goal>purge-local-repository</goal>
</goals>
<configuration>
<!-- Whether to purge only snapshot artifacts. -->
<snapshotsOnly>true</snapshotsOnly>
<actTransitively>false</actTransitively>
<reResolve>false</reResolve>
</configuration>
</execution>
<execution>
<id>unpack-dependencies</id>
<phase>validate</phase>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${dependencies.directory}</outputDirectory>
<markersDirectory>${dependencies.markers.directory}</markersDirectory>
<useBaseVersion>true</useBaseVersion>
<overWriteReleases>true</overWriteReleases>
<overWriteSnapshots>true</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
<excludeTransitive>false</excludeTransitive>
<useSubDirectoryPerArtifact>true</useSubDirectoryPerArtifact>
<stripVersion>true</stripVersion>
<stripClassifier>true</stripClassifier>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<id>assembly-single-zip</id>
<phase>prepare-package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<finalName>${project.build.finalName}</finalName>
<descriptors>
<descriptor>${assembly.file}</descriptor>
</descriptors>
<attach>false</attach>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.1</version>
<executions>
<execution>
<id>deploy-file-snapshot</id>
<phase>verify</phase>
<goals>
<goal>deploy-file</goal>
</goals>
<configuration>
<file>${deploy.file}</file>
<repositoryId>${nexus.repository.id}</repositoryId>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${project.version}</version>
<url>${nexus.repository.url}</url>
<pomFile>${nexus.deploy.pom}</pomFile>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.5.2</version>
<configuration>
<preparationGoals>clean</preparationGoals>
<tagBase>${release.tagBase}</tagBase>
<tagNameFormat>#{project.version}</tagNameFormat>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
...
Here we see that the plugins used in the build are dependency (to download dependencies), 'assembly' (to package), deploy (to deploy files to Nexus) and release--frankly I can't figure out how it is used. The scripts that I have (I'll describe later) don't use it explicitly and it doesn't seem to be executed in other standard build phases.
And in each of the solution the POM has parent of the configuration. And they look like this:
ProjA
<parent>
<groupId>MY.GROUP</groupId>
<artifactId>configuration</artifactId>
<version>1.0.1-SNAPSHOT</version>
</parent>
<groupId>MY.GROUP</groupId>
<artifactId>ProjA</artifactId>
<version>1.1.2-SNAPSHOT</version>
<packaging>pom</packaging>
<name>ProjA</name>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
</plugin>
</plugins>
</build>
...
In ProjB which depends on ProjA, the POM is like this:
<parent>
<groupId>MY.GROUP</groupId>
<artifactId>configuration</artifactId>
<version>1.0.1-SNAPSHOT</version>
</parent>
<groupId>MY.GROUP</groupId>
<artifactId>ProjB</artifactId>
<version>1.2.1-SNAPSHOT</version>
<packaging>pom</packaging>
<name>ProjB</name>
...
<dependencies>
<dependency>
<groupId>MY.GROUP</groupId>
<artifactId>ProjA</artifactId>
<version>1.1.2-SNAPSHOT</version>
<type>zip</type>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
</plugin>
</plugins>
</build>
...
3) Then some .bat scripts as well as deploy.pom and release.pom.
The deploy pom and release pom just simply replace the version numbers and declare the dependencies:
deploy.pom for ProjA:
<?xml version="1.0" encoding="utf-8"?>
<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>
<groupId>MY.GROUP</groupId>
<artifactId>ProjA</artifactId>
<version>1.1.2-SNAPSHOT</version>
<packaging>pom</packaging>
..<dependencies>...</dependencies>
By deploy I assume it means the the deployment of SNAPSHOT version as the version number indicates.
And the release.pom are basically the same but change the version to release version (in ProjA it is 1.1.1).
In each solution I also have some scripts which I believe are called by TeamCity. a) a file called download.bat, which basically calls mvn -U clean and then mvn -U validate. And b) a file called upload.bat which basically calls mvn prepare-package and then mvn verify. In both scripts we pass some mvn options like -DDeployPomFile, -DNexusUrl, -DRepositoryId. From the parent POM we can see some plugins are executed in those scripts too. And I guess the download.bat is called before TC is executing the VS build and upload.bat is called after the build (assume the target of the build is to publish the latest version).
Above is all I got. I suspect I still miss some TeamCity configuration because they are not stored in the SVN. But anyway, can somebody help figure out how to manage the daily build? Thank you very much!

How to get rid of duplicate class errors in Intellij for a Mavenized project using Lombok

I have a Maven managed Lombok project and I use Intellij. After building, I always get lots of errors in Intellij about duplicate classes because of the generated sources in target/generated-sources/delombok. Is there something I can do to git rid of these errors? Right now I just delete the target folder, but this is really irritating to have to do.
I have the standard configuration in Maven and the Lombok source code in is in src/main/lombok:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-maven-plugin</artifactId>
<version>1.16.8.0</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>delombok</goal>
</goals>
</execution>
</executions>
</plugin>
<profiles>
<profile>
<id>lombok-needs-tools-jar</id>
<activation>
<file>
<exists>${java.home}/../lib/tools.jar</exists>
</file>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-maven-plugin</artifactId>
<version>1.16.8.0</version>
<dependencies>
<dependency>
<groupId>sun.jdk</groupId>
<artifactId>tools</artifactId>
<version>1.8</version>
<scope>system</scope>
<systemPath>${java.home}/../lib/tools.jar</systemPath>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</profile>
</profiles>
According to delombok goal documentation: the default output directory is:
${project.build.directory}/generated-sources/delombok
I have found an JetBrains Team member comment stating that:
IDEA automatically excludes the build 'target' folder, providing that there are no generated sources under it, otherwise it excludes all sub-folders but the generated.
If you have some generated code or build artifacts that you want being excluded, you may put it under the 'target' folder.
This means that /generated-sources directory is by default not excluded and if you intend on excluding some files you should place them under parent /target directory and NOT under /generated-sources.
To achieve this you should configure the plugin and provide non-default <outputDirectory>:
<plugin>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-maven-plugin</artifactId>
<version>1.16.18.0</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>delombok</goal>
</goals>
</execution>
</executions>
<configuration>
<sourceDirectory>src/main/java</sourceDirectory>
<outputDirectory>${project.build.directory}/delombok</outputDirectory>
<addOutputDirectory>false</addOutputDirectory>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
This will stop IDEA from yielding Duplicate class found in (...) warnings.
I tried Krzusiek's solution but IntelliJ would still mark my source files from src/main/java as duplicated.
After many failed attempts to tweak the lombok-maven-plugin I eventually decided to get rid of the delombok folder after compilation. That folder only server as an intermediary stage for compilation (in my case I needed it to use lombok with AspectJ compiler via the aspectj-maven-plugin) and there's no real need to keep it once your source files have been compiled.
Manually removing the delombok folder after each compilation is a real bummer, so I just configured an additional execution of the maven-clean-plugin which would specifically target the delombok folder.
Your POM should contain:
<build>
<sourceDirectory>${project.build.directory}/generated-sources/delombok</sourceDirectory>
<plugins>
<!-- will delombok source files into /target/generated-sources/delombok -->
<plugin>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-maven-plugin</artifactId>
<version>1.16.16.0</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>delombok</goal>
</goals>
</execution>
</executions>
<configuration>
<addOutputDirectory>false</addOutputDirectory>
<sourceDirectory>src/main/java</sourceDirectory>
</configuration>
</plugin>
<!-- other plugins bound to compile phase should go here -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<executions>
<execution>
<id>delombok-removal</id>
<phase>compile</phase>
<goals>
<goal>clean</goal>
</goals>
<configuration>
<excludeDefaultDirectories>true</excludeDefaultDirectories>
<filesets>
<fileset>
<directory>${project.build.sourceDirectory}/com</directory> <!-- assuming your root package is something like com.mycompany -->
</fileset>
</filesets>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
The idea is to remove generated-source from sources. I could do it from Project Structure -> Select from the list of packages and in right hand side find the folders that are being used to derive sources for that package. If you find generated-source in that list remove it.
you just need to unmark the folder with generated sources in Intellij and will be fine.
Firstly, you have to apply to Krzysiek's answer - move generated_sources directory under target so it will be /target/generated_sources. The next step is to unmark given directory as generated sources root. Then you have to right click on given project in Intellij, select Maven and then Reload project. After that do the same but this time go Maven -> Generate Sources and Update Folders. If you have multi module project and one module depends on each other i.e. module A depends on B then you have to start with B first.
This solution suggested by Andrey Dernov here worked for me with Maven.
Enable Settings (Preferences on macOS) > Build, Execution, Deployment > Build Tools > Maven > Runner > Enable "Delegate IDE build/run actions to maven" option

Is it possible to get the list of active profiles in Maven?

In Maven, is there a way to get a list of the active profiles, say, as a property or as a text file?
More specifically, when I run:
mvn resources:resources -P MyProfile
I want to get the string MyProfile somewhere I can read it into my Java program.
Maven 3.2.1
Thanks
Edit
I attempted to configure the Maven Help plugin to run the active-profiles goal whenever the goal resources:resources is run by configuring an execution to participate in the process-resources phase as shown below. That did not work either ...:
<packaging>jar</packaging>
<build>
<plugins>
<!-- ... -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-help-plugin</artifactId>
<version>2.2</version>
<configuration>
<output>${basedir}/target/active-profiles.txt</output>
</configuration>
<executions>
<execution>
<phase>process-resources</phase>
<goals>
<goal>active-profiles</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
You could try this maven plugin. The configuration below will create a text file that will contain the profiles that were active during the build.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-help-plugin</artifactId>
<version>2.2</version>
<configuration>
<output>${basedir}/target/active-profiles.txt</output>
</configuration>
</plugin>

How to manage artifactory / maven artifact using different profiles

i have some problems understanding how to manage different "jar" files generated using different profiles.
An example. I have a project : my.project:sample:1.0
And we use two profiles:
Using Profile1 is compiling using java 7 and with dependency other:project:1.0
Using Profile2 is compiling using java 6 and with dependency different:project:3.0
Using command line in local environment is easy to manage, but I don't know how to store and manage it on artifactory.
We have two different projects that use the same library but generated using different profiles:
A Project require my.project:sample:1.0 - Profile1"
Another project require my.project:sample:1.0 - Profile2"
How can I specify those depedency with the library and the profile?
Clarification: The generated Jar it's storing using artifactory, and the projects resolve the dependencies using the repository. I can't use the project as a module.
You can use classifier to make the distinction between artifacts and reuse the classifier in the dependency.
defining a classifier
To do so you need to define the classifier in maven-jar-plugin:
<profiles>
<profile>
<id>profile1</id>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<classifier>jdk6</classifier>
</configuration>
</execution>
</executions>
<plugin>
<plugins>
</build>
</profile>
<profile>
<id>profile2</id>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<classifier>jdk7</classifier>
</configuration>
</execution>
</executions>
<plugin>
<plugins>
</build>
</profile>
</profiles>
using the classifier in dependency
Very simple:
<dependency>
<groupId>myGroup</groupId>
<artifactId>myArtifact</artifactId>
<classifier>jdk6</classifier>
<dependency>

Resources