Compatibility problem between maven and maven-resources-plugin - java

I'm using maven-resources-plugin to copy a file from resources dir to output dir and inject a variable;
there is the pom of the project:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.4</version>
<configuration>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</plugin>
the resource file is something like this:
operation=${var}
and in he pom there is:
<properties>
<operation>true</operation>
</properties>
When I build the project (mvn -U clean package ) locally everything works fine: the file .properties is correctly inside the jar and it contains "operation=true".
The problem appears when I deploy the jar to my artifactory. If I download and open the jar from artifactory I can still find the .properties file, but in this case it contains: "operation=${var}" (the plugin doesn't inject the value of the variable). The command for the build inside the .yml file is the same that I run locally (mvn -U clena package). Any suggestions? The only difference that I can see is that on my computer I have maven 3.6.1 and on the server where I build the project for artifactory there is maven 3.3.3.

Related

Include files from a JAR in a dependent project

I'd like to synchronize log4j and logback config files across multiple projects. I have one project (Project A) that contains the log4j and logback dependencies, along with the config files.
Project A
src/test/resources
log4j2.xml
logback-test.xml
Project B has a dependency on Project A. I would like to include the log config files in Project A's JAR and have them automatically put in a specific target folder in Project B when resolving Maven dependencies for Project B.
I have tried maven-jar-plugin in Project A but it doesn't seem to work for my purpose.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<includes>
<include>src/test/resources/log4j2.xml</include>
<include>src/test/resources/logback-test.xml</include>
</includes>
</configuration>
</plugin>
Any help would be appreciated.
Thanks!
UPDATE:
While Eugene's answer was accepted, I needed to add a <resources> entry so the log config files would be included in the packaged JAR.
<build>
<resources>
<resource>
<directory>src/test/resources</directory>
<includes>
<include>log4j2.xml</include>
<include>logback-test.xml</include>
</includes>
</resource>
</resources>
</build>
Executing mvn clean compile assembly:single deploy from Project A created and deployed the JAR with the log files included.
[INFO] --- maven-remote-resources-plugin:1.7.0:bundle (default) # project-a ---
[INFO] Writing META-INF/maven/remote-resources.xml descriptor with 2 entries
Executing mvn clean compile from Project B copied the files into the output directory
[INFO] --- maven-remote-resources-plugin:1.7.0:process (default) # project-b ---
[INFO] Preparing remote bundle com.my.projects:project-a:1.0-SNAPSHOT
[INFO] Copying 2 resources from 1 bundle.
You can use Apache Maven Remote Resources Plugin
This plugin is used to retrieve JARs of resources from remote
repositories, process those resources, and incorporate them into JARs
you build with Maven.
A very common use-case is the need to package certain resources in a
consistent way across your organization. For example at Apache, it is
required that every JAR produced contains a copy of the Apache license
and a notice file that references all used software in a given project
Define in Project A which resources you want to share or better create separate project for shared resources
<build>
<plugins>
<plugin>
<artifactId>maven-remote-resources-plugin</artifactId>
<version>1.7.0</version>
<executions>
<execution>
<goals>
<goal>bundle</goal>
</goals>
</execution>
</executions>
<configuration>
<resourcesDirectory>src/test/resources/</resourcesDirectory>
<includes>
<include>log4j2.xml</include>
<include>logback-test.xml</include>
</includes>
</configuration>
</plugin>
</plugins>
</build>
Maven will create resources bundle file for sharing resources
${basedir}/target/classes/META-INF/maven/remote-resources.xml
<remoteResourcesBundle xsi:schemaLocation="http://maven.apache.org/remote-resources/1.1.0 https://maven.apache.org/xsd/remote-resources-1.1.0.xsd"
xmlns="http://maven.apache.org/remote-resources/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<remoteResources>
<remoteResource>log4j2.xml</remoteResource>
<remoteResource>logback-test.xml</remoteResource>
</remoteResources>
<sourceEncoding>UTF-8</sourceEncoding>
</remoteResourcesBundle>
See documentation
Configure other modules to use the shared resources
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-remote-resources-plugin</artifactId>
<version>1.7.0</version>
<configuration>
<outputDirectory>[your output directory]</outputDirectory>
<resourceBundles>
<!--The resource bundles that will be retrieved and processed. For example: org.test:shared-resources:${project.version}-->
<resourceBundle>groupId:artifactId:version[:type[:classifier]]</resourceBundle>
</resourceBundles>
</configuration>
<executions>
<execution>
<goals>
<goal>process</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
See documentation
Alternative solution:
Apache Maven Dependency Plugin It can copy and/or unpack artifacts from local or remote repositories to a specified location.
It was described there Maven: Extract dependency resources before test
and there Use a dependency's resources?
UPDATE:
Example how to add resources:
<project>
...
<build>
...
<resources>
<resource>
<directory>[your folder 1 here]</directory>
</resource>
<resource>
<directory>[your folder 2 here]</directory>
</resource>
</resources>
...
</build>
...
</project>
See documentation
Please don't put logging configuration files into JARs, if someone depends on your JAR, your configuration may overwrite theirs. That depends on which JAR is loaded first
If you want, like this. And package them into JAR
src/main/resources
log4j2.xml
logback.xml

Generate docker image by maven plugin

I have manually written dockerfile but now I need configure maven to create that file and build image. I'm trying do it with spotify's maven plugin.
Here is dockerfile which is written by me and it works:
FROM tomcat:8.0-jre8
RUN rm -rvf /usr/local/tomcat/webapps/ROOT
COPY ./context.xml /usr/local/tomcat/conf/
COPY /target/brainis-1.0-SNAPSHOT.war /usr/local/tomcat/webapps/ROOT.war
CMD ["catalina.sh", "run"]
EXPOSE 8080
I need ensure my maven plugin generate same docker file before build image. Can you tell me please how to achieve it? My current configuration generates only first command FROM tomcat:8.0-jre8, how to configure rest of that file in maven?
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<configuration>
<imageName>spring-tomcat</imageName>
<baseImage>tomcat:8.0-jre8</baseImage>
</configuration>
</plugin>
You need to add your Dockerfile to your codebase, i.e. /src/main/docker/Dockerfile and reference it from Spotify's Maven plugin this way:
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>${docker.plugin.version}</version>
<configuration>
<imageName>${docker.image.prefix}/${project.artifactId}</imageName>
<dockerDirectory>${project.basedir}/src/main/docker</dockerDirectory>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.war</include>
</resource>
</resources>
</configuration>
</plugin>
The last part, resources, places the docker build base path in whichever folder you want it, i.e. /target and which files to include.
That will run your whole Dockerfile script

.dat files not packaged in jar in Netbeans

I have a maven Java project projA that build into a jar.
I have another maven Web project projB that holds a dependency of projA.
In proj A one of my classes accesses the resources located in the packages in projA.
When I expand the jar shown under dependencies in projB, I see that it does not contain the resource files (.dat).
What setting I need to do to copy these files into the jar when I build my projA in Netbeans
I am using NetBeans IDE 8.0.2 / Java 1.8
In your pom.xml, include something along the line like this:
<build>
<resources>
<resource>
<filtering>false</filtering>
<directory>src/main/java</directory>
<includes>
<include>**/*.dat</include>
</includes>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</resource>
</resources>
[...]

Resource files not found from JUnit test cases

Summary
My JUnit tests are not finding the files they require during execution.
I'm using Maven for dependency management and compilation.
Details
All files required by the test cases are located in: src/test/resources.
For example, src/test/resources/resourceFile.txt.
To access a resource I use the following code:
URL url = getClass().getResource("/resourceFile.txt").getFile();
File file = new File(url);
But then file.exists() returns false. And the error I get is:
Tests in error:
myJUnitTestCase(tests.MyJUnitTestClass): /home/me/workspace/Project%20Name/target/test-classes/resourceFile.txt (No such file or directory)
Note, the following gives the same error (notice the removed / prefix):
URL url = getClass().getClassLoader().getResource("resourceFile.txt").getFile();
File file = new File(url);
It seems as though the files from src/test/resources are not getting copied into target/test-classes.
Any ideas?
The following questions did not help
Why Can't I access src/test/resources in Junit test run with Maven?
Loading Properties File In JUnit #BeforeClass
How to deal with the test data in Junit?
Software Versions
Ubuntu 12.04
Apache Maven 2.2.1
Java 1.7.0
Eclipse (Java EE IDE for Web Developers) Indigo Service Release 2
(truncated) Maven POM
<?xml version="1.0" encoding="UTF-8"?>
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.groupId</groupId>
<artifactId>artifactId</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>name</name>
<build>
<finalName>name</finalName>
<directory>target</directory>
<outputDirectory>target/classes</outputDirectory>
<testOutputDirectory>target/test-classes</testOutputDirectory>
<sourceDirectory>src/main/java</sourceDirectory>
<testSourceDirectory>src/test/java</testSourceDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
<testResources>
<testResource>
<directory>src/test/resources</directory>
</testResource>
</testResources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
My mistake, the resource files WERE actually copied to target/test-classes. The problem seemed to be due to spaces in my project name, e.g. Project%20Name.
I'm now loading the file as follows and it works:
org.apache.commons.io.FileUtils.toFile(myClass().getResource("resourceFile.txt")‌​);
Or, (taken from Java: how to get a File from an escaped URL?) this may be better (no dependency on Apache Commons):
myClass().getResource("resourceFile.txt")‌​.toURI();
You know that Maven is based on the Convention over Configuration pardigm? so you shouldn't configure things which are the defaults.
All that stuff represents the default in Maven. So best practice is don't define it it's already done.
<directory>target</directory>
<outputDirectory>target/classes</outputDirectory>
<testOutputDirectory>target/test-classes</testOutputDirectory>
<sourceDirectory>src/main/java</sourceDirectory>
<testSourceDirectory>src/test/java</testSourceDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
<testResources>
<testResource>
<directory>src/test/resources</directory>
</testResource>
</testResources>
This is actually redundant except in cases where you want to override the defaults. All of these settings are implied defaults.
You can verify that by checking your effective POM using this command
mvn help:effective-pom
<finalName>name</finalName>
<directory>target</directory>
<outputDirectory>target/classes</outputDirectory>
<testOutputDirectory>target/test-classes</testOutputDirectory>
<sourceDirectory>src/main/java</sourceDirectory>
<testSourceDirectory>src/test/java</testSourceDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
<testResources>
<testResource>
<directory>src/test/resources</directory>
</testResource>
</testResources>
For example, if i want to point to a different test resource path or resource path you should use this otherwise you don't.
<resources>
<resource>
<directory>/home/josh/desktop/app_resources</directory>
</resource>
</resources>
<testResources>
<testResource>
<directory>/home/josh/desktop/test_resources</directory>
</testResource>
</testResources>
You may have defined:
<packaging>pom</packaging>
If you did this, the resources won't be present in the target directory when you will launch your tests. And mvn package won't create it either.
At the contrary, if you define:
<packaging>jar</packaging>
Or nothing as the default value is jar. As Maven is based on Convention over Configuration. You will end up with:
src/main/resources => target/classes
src/test/resources => target/test-classes
Main classes should be under src/main/java
and
test classes should be under src/test/java
If all in the correct places and still main classes are not accessible then
Right click project => Maven => Update Project
Hope so this will resolve the issue
The test Resource files(src/test/resources) are loaded to target/test-classes sub folder. So we can use the below code to load the test resource files.
String resource = "sample.txt";
File file = new File(getClass().getClassLoader().getResource(resource).getFile());
System.out.println(file.getAbsolutePath());
Note : Here the sample.txt file should be placed under src/test/resources folder.
For more details refer options_to_load_test_resources
Make 'maven.test.skip' as false in pom file, while building project test reource will come under test-classes.
<maven.test.skip>false</maven.test.skip>

Refer to Maven project paths from Java

I need to programmatically gather some paths inside a Maven project, in particular to refer to the project artifact.
Using
URL MyClass.class.getClassLoader().getResource(String name)
works for a path relative to the target/classes folder of the project, but since the artifact sits in the target folder it is not possible to reference it. A path like
System.getProperty("user.dir") + "/target"
does not convince me at all at least for the fact that the target folder name, while standard, is not safely portable.
Is there a Maven-aware library solution that exploits a relative path?
MavenProperties can be written to a manifest file using the maven archiver which is used by the maven war plugin or the maven jar plugin.
If you have a web app, then you can pass some information to the web.xml file, too.
This is an example of one of my projects:
from pom.xml:
------------------------------------------------
<properties>
<maven.build.timestamp.format>dd.MM.yyyy' 'HH:mm:ss</maven.build.timestamp.format>
<build-version>${env.SVN_REVISION}</build-version>
<build-date>${maven.build.timestamp}</build-date>
</properties>
.
.
.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.0.2</version>
<configuration>
<webResources>
<webResource>
<directory>${basedir}/src/main/webapp/WEB-INF</directory>
<includes>
<include>web.xml</include>
</includes>
<targetPath>WEB-INF</targetPath>
<filtering>true</filtering>
</webResource>
</webResources>
from web.xml:
------------------------------------------------
<context-param>
<param-name>BUILD_VERSION</param-name>
<param-value>${build-version}</param-value>
</context-param>
<context-param>
<param-name>BUILD_DATE</param-name>
<param-value>${build-date}</param-value>
</context-param>

Categories