How to filter resource in Maven, replacing with a dependencies artifactId? - maven-2

I'm trying to build a jar that has an xml file as a resource. I'd like to apply a filter to that xml to insert the name of a dependency into the xml. The filtering is working, because I was able to drop in ${project.build.finalName} and get it replaced. I found one hint that the property I'm looking for might be
${project.dependencies[0].artifactId}
but that doesn't seem to work. I'm looking to replace
<fileName>${project.dependencies[0].artifactId}</fileName>
with
<fileName>OtherLibrary</fileName>
Is that possible?
xml, which is in src/main/resources:
<somenode>
<fileName>${project.dependencies[0].artifactId}</fileName>
</somenode>
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>com.foo</groupId>
<artifactId>Thing</artifactId>
<version>1.0-SNAPSHOT</version>
<name>Thing</name>
<url>http://maven.apache.org</url>
<build>
<resources>
<resource>
<directory>${basedir}/src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
<dependencies>
<dependency>
<groupId>com.pts</groupId>
<artifactId>OtherLibrary</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

Damn, you're right, this property doesn't get replaced during the filtering of resources. That's weird and it sounds like a bug in the Maven Resources Plugin because this property is correctly interpolated during the process-resources phase as I'll demonstrate in the workaround I'm suggesting below (based on the maven-antrun-plugin and the replace task).
First, add the following to your POM:
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>process-resources</phase>
<configuration>
<tasks>
<echo>${project.dependencies[0].artifactId}</echo><!-- I'm a test -->
<replace file="${project.build.outputDirectory}/myxmlfile.xml"
token="###" value="${project.dependencies[0].artifactId}"/>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
Then, update your XML file into:
<somenode>
<fileName>###</fileName>
</somenode>
With these changes, running mvn process-resources would produce the following result:
$ cat target/classes/myxmlfile.xml
<somenode>
<fileName>OtherLibrary</fileName>
</somenode>
Which proves the property is interpolated (but not set during maven filtering of resources)1. And if you need to filter more than one file, the replace task can take a fileset. Adapt it to suit your needs.
1 Actually, it would be nice to create a new Jira for this bug in the Maven 2.x Resources Plugin. I've created MRESOURCES-118.

The indexed properties will only be available inside plugin configuration due to the way Maven interpolates the POM - so it is available to antrun's replace task, but not the filtering.
However, accessing dependencies by index is not very robust - it is susceptible to changes in the parent. You might instead use the following in pom.xml:
<properties>
<fileName>some-name</fileName>
</properties>
...
<dependency>
<groupId>your.group.id</groupId>
<artifactId>${fileName}</artifactId>
...
</dependency>
You can then continue to filter using the property name:
<somenode>
<fileName>${fileName}</fileName>
</somenode>

Related

Intellij Create Test missing JUnit

I try to create an test class and test it using JUnit, but in my Intellij is missing JUnit library.
What I need to do to have at library option with JUnit?
Add junit-jupiter artifact in Maven
If using Apache Maven to configure your project, and writing JUnit 5 Jupiter to write you tests, add a dependency to your project.
JUnit 5.4 simplified things by providing this new Maven artifact, junit-jupiter. This one aggregate artifact provides all you need to write and run JUnit 5 tests. Previous to 5.4, you had to add multiple artifacts — confusing and messy.
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.5.0-M1</version>
<scope>test</scope>
</dependency>
Here is an example, an entire POM file. I started an app using the maven-archetype-quickstart artifact. Next I changed all the versions numbers to the latest, as of this week shown here. Lastly, I replaced the old JUnit 4 dependency with the new JUnit 5 dependency.
<?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>work.basil.example</groupId>
<artifactId>method-lister</artifactId>
<version>1.0-SNAPSHOT</version>
<name>method-lister</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>12</maven.compiler.source>
<maven.compiler.target>12</maven.compiler.target>
</properties>
<dependencies>
<!--<dependency>-->
<!-- <groupId>junit</groupId>-->
<!-- <artifactId>junit</artifactId>-->
<!-- <version>4.11</version>-->
<!-- <scope>test</scope>-->
<!--</dependency>-->
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.5.0-M1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M3</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.1</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>3.0.0-M1</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>3.0.0-M1</version>
</plugin>
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
JUnit plugins
Be sure the IntelliJ plugin for JUnit is installed and enabled. Verify the checkmark is checked, meaning enabled. (You can disable unneeded plugins to save memory and launch time.)
Generate Test dialog
Your IntelliJ 2019.1 dialog for Generate > Test… should look like this.

How to add multiple source directories to pom.xml

I am getting package org.testng.annotations does not exist error when I am trying to compile multiple source directories using maven. I am running webdriver tests and all of my tests are importing import org.testng.annotations. I am using IntelliJ 12 and my src directory looks like this -
src
-->main
--> java
--> package1
--> file1.java
--> package2
--> file2.java
-->test
--> java
--> package1
--> file1.java
--> file2.java
--> package2
--> package3
--> package4
--> package5
--> package6
and the build plugin I am using in the pom.xml looks like this -
<?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">
<parent>
<artifactId>core-xxxxx</artifactId>
<groupId>core-xxxxx</groupId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>tests</artifactId>
<dependencies>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-api</artifactId>
<version>2.32.0</version>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<directory>target</directory>
<outputDirectory>target/classes</outputDirectory>
<testOutputDirectory>target/test-classes</testOutputDirectory>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>src/main/java</source>
<source>src/test/java</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
why am I getting the org.testng.annotations not found error?
The default layout for a maven project is the following:
src
main
java
test
java
within the src/main/java/ directory the package name for you productive java class source files should added. within the src/test/java/ the package name for the unit tests java class source files.
And you should NOT change the layout if you don't have really really good reasons to do so.
Furthermore redefining the defaults of Maven defaults (target, target/classes, target/test-classes etc.) is against the convention over configuration paradigm.
Be aware that you need to follow a naming convention for unit tests which means you unit tests should be named like the following:
<includes>
<include>**/*Test*.java</include>
<include>**/*Test.java</include>
<include>**/*TestCase.java</include>
</includes>
But in your case I assume that we are talking about integration tests which means you need to use the following naming convention
<includes>
<include>**/IT*.java</include>
<include>**/*IT.java</include>
<include>**/*ITCase.java</include>
</includes>
Apart from that you should now that unit tests in Maven will be executed by the maven-surefire-plugin whereas the integration tests will be executed by the maven-failsafe-plugin.
To get around the testng annotations not found errors I ended up moving the base class from src/main/java/package1/baseclass.java to src/main/test/package1/baseclass.java and the testng annotations errors resolved

How to change the qualifier in the file names of plugins and features

I am trying to rename my artifacts in the repository folder of my eclipse-repository module. At the moment they are auto generated like ...1.0.0.v20130315-1927.jar.
I haven't found any configuration parameter that works. I have tried to use the qualifier setting in the configuration (see tycho-p2-repository-plugin), but it doesn't work.
<?xml version="1.0" encoding="UTF-8"?>
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>development.statTool</groupId>
<artifactId>Application</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>development.statTool</groupId>
<artifactId>development.statTool.p2</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>eclipse-repository</packaging>
<properties>
<tycho-version>0.16.0</tycho-version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.eclipse.tycho</groupId>
<artifactId>tycho-p2-repository-plugin</artifactId>
<version>${tycho-version}</version>
<configuration>
<qualifier>abcd</qualifier>
</configuration>
</plugin>
</plugins>
</build>
</project>
My solution is to use the tycho-packaging-plugin. Only "disadvantage" changing the build qualifier needs to rebuild all modules contained by the repository.
Here the part out of my parent pom.xml:
<plugin>
<groupId>org.eclipse.tycho</groupId>
<artifactId>tycho-packaging-plugin</artifactId>
<version>${tycho.version}</version>
<dependencies>
<dependency>
<groupId>org.eclipse.tycho.extras</groupId>
<artifactId>tycho-buildtimestamp-jgit</artifactId>
<version>${tycho-extras.version}</version>
</dependency>
</dependencies>
<configuration>
<strictBinIncludes>false</strictBinIncludes>
<format>'rev${rev}-'yyyyMMdd-HHmm</format>
</configuration>
</plugin>
try this:
mvn -Dtycho.mode=maven org.eclipse.tycho:tycho-versions-plugin:set-version -DnewVersion=13.3.0.1-SNAPSHOT
or simply search text "1.0.0-SNAPSHOT" and replace it with "13.3.0.1" using Actual Search and Replace tool.

Maven WAR Overlays - including unpacked dependencies

I'm trying to set up a project using Maven and am a bit stuck with how to include some third party dependencies that need to be included unpacked in the resultant war file.
My project contains some custom ColdFusion code and includes Java dependencies, including ColdFusion packaged as a war file. I then am attempting to include some 3rd party ColdFusion code, which I've installed in my maven repository packaged as a jar, but I actually want to deploy it unpacked in the resultant war file. It's this unpacking of the 3rd party libraries that I'm stuck with. I'd really like this to be done BEFORE the war is build, so that I can use war:exploded during the development.
Currently my pom.xml looks something like this:
<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.mycompany.app</groupId>
<artifactId>my-webapp</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>my-webapp Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<!-- This is the war overlay -->
<dependency>
<groupId>com.adobe.coldfusion</groupId>
<artifactId>coldfusion</artifactId>
<version>9.0.1</version>
<type>war</type>
<scope>runtime</scope>
<optional>false</optional>
</dependency>
<!-- This is the 3rd party ColdFusion dependency -->
<dependency>
<groupId>org.corfield</groupId>
<artifactId>fw1</artifactId>
<version>1.2RC2A</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>my-webapp</finalName>
</build>
</project>
I've kind of got it doing what I want by modifying the build section as follows:
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack</id>
<phase>package</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.corfield</groupId>
<artifactId>fw1</artifactId>
<version>1.2RC2A</version>
<type>jar</type>
<overWrite>true</overWrite>
<outputDirectory>${project.build.directory}/${project.artifactId}</outputDirectory>
<includes>**/*.cfc</includes>
</artifactItem>
</artifactItems>
<includes>**/*.cfc</includes>
<outputDirectory>${project.build.directory}/${project.artifactId}</outputDirectory>
<overWriteReleases>false</overWriteReleases>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
The problem with this is that the package:unpack happens after the war is built, so the unpacked dependecies are not in the resulting war file.
I have also tried a few things with the assembly plugin and I came fairly close also by using something like this:
<assembly>
<id>${project.artifactId}</id>
<formats>
<format>war</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<includes>
<include>org.corfield:fw1</include>
</includes>
<unpack>true</unpack>
<outputDirectory>/</outputDirectory>
</dependencySet>
<dependencySet>
<excludes>
<exclude>org.corfield:fw1</exclude>
</excludes>
<unpack>false</unpack>
<outputDirectory>/WEB-INF/lib</outputDirectory>
</dependencySet>
</dependencySets>
<fileSets>
<fileSet>
<directory>src/main/webapp</directory>
<outputDirectory>/</outputDirectory>
</fileSet>
</fileSets>
</assembly>
However that created a second war file named something like my-webapp-1.0-SNAPSHOT-my-webapp.war as well as the my-webapp-1.0-SNAPSHOT.war. The my-webapp-1.0-SNAPSHOT-my-webapp.war also included my-webapp-1.0-SNAPSHOT.war
At the end of the day I want my resultant war to look like:
org
|-- corfield
|-- framework.cfc
WEB-INF
|-- lib
|-- web.xml
index.cfm
(in reality there's a lot more to it than that, but that's enough to illustrate the point hopefully)
I think I'm pretty close but I'm just missing something I need. I'd be extremely grateful for any assistance.
For the maven-dependency-plugin approach, bind the unpack goal on the prepare-package phase (Maven 2.1+) instead of package.
References
Lifecycle Reference
Have you looked at the overlay option with maven-war-plugin? It esstentially allows you to unpack the ColdFusion war on top your site layout. I've done this with a combination of ColdFusion 9.x and Struts2. Doing a ColdFusion only overlay should make it real easy. You may want to create the ColdFusion war first. You can also then control the neo-*.xml files from your Maven project as well.

Problems with maven output directory

I'm using almost same POM for both my projects, they are on the same workspace but they are not related at all, they are related however because in both I use spring and jboss. Here is the pom :
<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.springinaction.hello</groupId>
<artifactId>spring-in-action</artifactId>
<packaging>jar</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>spring-in-action</name>
<url>http://maven.apache.org</url>
<properties>
<jboss.ome>C:\jboss-5.1.0.GA\server\default\deploy</jboss.ome>
<springversion>2.5.3</springversion>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
<version>${springversion}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.0</version>
<configuration>
<warName>spring-book</warName>
<outputDirectory>${jboss.ome}</outputDirectory>
</configuration>
</plugin>
</plugins>
</build>
</project>
What I want to achieve with this POM is that I want to name my war when built spring-book.war and copy it to Jboss location I specified. Now in my first project this works it does exactly what I requested but in other it does not. I changed springversion and jboss home properties variable but everything remains the same, what can I do ? The project builds and all, everything is working perfectly just I don't want to copy everytime in my jboss dir and previously remove the old war, it takes about 20sec on each source code change its a lot
Problem spotted at this line:
<packaging>jar</packaging>
You're not using the right packaging, it should be:
<packaging>war</packaging>
After this change the war plugin should get called and things should work like in the other project :)
You could leave the output directory at its default, and use a profile instead with the maven jboss plugin. It has a hard-deploy target which copies your artifact to the deploy directory. If it's in a profile, you can activate it when (and only when) you want.
Moreover, with the antrun plugin, you can also delete the old war file before copying over the new one (this is useful when the war filename includes the version, but in your case may not be needed).
<profiles>
<profile>
<id>deploy</id>
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>remove-old-war</id>
<phase>prepare-package</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<delete>
<fileset dir="${jboss.ome}"
includes="*.war"/>
</delete>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jboss-maven-plugin</artifactId>
<executions>
<execution>
<id>redeploy-server</id>
<phase>pre-integration-test</phase>
<goals>
<goal>hard-deploy</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
You can then activate the profile with
mvn -Pdeploy install