I have two projects which are built from one maven multiproject, project A and project B. Project B recently came to live and differ only little from project A, namely it uses a couple of different configuration files. My idea was to create a profile for projectB and add additional configuration files / replace existing configuration files. I've tried several approaches on stackoverflow including copy-rename plugin and mvn dependency plugin. Part of the problem seems to be that both projects have a file with same config name.
My current/last approach was to use maven-resources-plugin in following way:
I created an additional directory: src/main/projectbresources and a projectbprofile:
<profile>
<id>projectb</id>
<activation><activeByDefault>false</activeByDefault></activation>
<build>
<plugins>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
<executions>
<execution>
<id>copy-resources</id>
<!-- here the phase you need -->
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/${project.build.finalName}/WEB-INF/classes</outputDirectory>
<resources>
<resource>
<directory>src/main/projectbresources</directory>
<filtering>true</filtering>
</resource>
</resources>
<overwrite>true</overwrite>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
I have a file with same name in both src/main/resources and src/main/projectbresources however, no matter the profile I build with, always the file from src/main/resources is in the target folder. Additional files that are in projectbresources only are copied to target.
Based on your statement "Project B recently came to live and differ only little from project A, namely it uses a couple of different configuration files." I would say you don't need 2 separate projects. You can have only one project and based on activated profile choose different configurations. With this approach the configuration files for both cases can have same name but different content.
Your project structure will look like (as an example):
project root folder:
pom.xml
- src
-- main
--- resources-profileA
--- resources-profileB
Now, the pom.xml contains 2 profiles: profileA and profileB. Each profile define it's own build/resources.
<profiles>
<profile>
<id>projectA</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<build>
<resources>
<resource>
<directory>src/main/resources-profileA</directory>
</resource>
</resources>
</build>
</profile>
<profile>
<id>projectB</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<build>
<resources>
<resource>
<directory>src/main/resources-profileB</directory>
</resource>
</resources>
</build>
</profile>
</profiles>
More on that, you can make one profile active by default. This will help your dev environment to automatically use one. If you like to have a default active profile for that profile you can name the resource folder just resources (default maven name) and keep different name for second profile.
UPDATE:
To go 'easy' and only add some additional files, you can use for profile projectA the maven defaults and define onle a profile for projectB.
The project root folder become:
pom.xml
- src
-- main
--- resources
--- resources-profileB
and the pom.xml will contains only one profile inactive by default:
<profiles>
<profile>
<id>projectB</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<build>
<resources>
<resource>
<directory>src/main/resources-profileB</directory>
</resource>
</resources>
</build>
</profile>
</profiles>
How to build for the two profiles:
Build for no profile is equivalent of building for projectA:
mvn clean install
Buid for projectB profile will ignore resources in default folder and will use only resources defined in profile (src/main/resources-profileB).
mvn clean install -P projectB
Related
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
I am working on a spring-boot application. I have two profiles inside my POM, but when I am trying the build the project using clean install -Pdev its not reflecting the change in application.properties, it'll only reflect when I am using 'activeByDefault' tag in one of the profile.
<profiles>
<profile>
<id>dev</id>
<properties>
<activatedProperties>dev</activatedProperties>
</properties>
</profile>
<profile>
<id>release</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<properties>
<activatedProperties>release</activatedProperties>
</properties>
</profile>
</profiles>
If I am running clean install -Pdev I am getting this in my application.properties.
activatedProperties=#activatedProperties#
If I am setting the <activeByDefault>true</activeByDefault> then I'll get the value inside application.properties.
activatedProperties=release.
The frustration is I am not able to use other profiles.
Add in your application.properties
spring.profiles.active=#activatedProperties#
If Maven doesn't find the directory which contains your application.properties file in runtime, you need to setup the Maven Resources Plugin to filter the directory.
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
...
</build>
Or just add what profile you want to active in application.properties
spring.profiles.active=dev
NOTE: The Maven profile and the Spring profile are different things.
I'm trying to configure my application to have 2 build profiles: development and production. In order to do that, I created two subdirectories under the src/main/resources folder: src/main/resources/development and src/main/resources/production. Each subdirectory has its own .properties files.
<profiles>
<profile>
<id>development</id>
<build>
<resources>
<resource>
<directory>src/main/resources/development</directory>
</resource>
</resources>
</build>
</profile>
<profile>
<id>production</id>
<build>
<resources>
<resource>
<directory>src/main/resource/production</directory>
</resource>
</resources>
</build>
</profile>
</profiles>
I build the app with the command mvn install -P ${profile_here}
Maven copies the content of the folder related to the chosen profile to the WEB-INF/classes output directory, however the development and production folders are copied as well.
WEB-INF/classes
WEB-INF/classes/development
WEB-INF/classes/production
How can I solve this problem?
Thanks in advance.
The maven-war-plugin is rather limited when it comes to resources. However, you could use the maven-resources-plugin to include/exclude resources like described here: https://maven.apache.org/plugins/maven-resources-plugin/examples/include-exclude.html
we have a project which initially was developed to run on a linux platform, we want to customize it and use it under windows platform. It is hosted on github. Any advice on how to manage files that are shared between the two platforms but have some specificity for each one. for example configuration files that contains paths, environment variables and the like.
thanks for suggestion.
Since you have tagged maven here is the solution, use profiles to differentiate between linux and windows.
<profiles>
<profile>
<id>linux</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<envName>linux</envName>
</properties>
</profile>
<profile>
<id>windows</id>
<properties>
<envName>windows</envName>
</properties>
</profile>
</profiles>
<build>
<outputDirectory>${project.basedir}/target/classes</outputDirectory>
<sourceDirectory>${project.basedir}/src/main/java</sourceDirectory>
<resources>
<resource>
<directory>${basedir}/src/main/java</directory>
<includes>
<include>**/*.class</include>
</includes>
</resource>
<resource>
<targetPath>${project.basedir}/target/classes/configurations</targetPath>
<directory>${basedir}/src/main/resources/configurations/${envName}</directory>
</resource>
</resources>
<plugins>
</build>
Say suppose you have some configuration files specific to OS. and when you want to build based on the enivronment you want the file to copied to configurations directory inside class, the above code snippet copies that. For that to work you need to create 2 directories inside src/main/resoruces/configurations/linux and src/main/resources/configurations/windows. when you run maven you need to use profile like mvn package -Plinux or mvn package -Pwindows.
I am using JNDI to read database configuration from my application's context.xml. The way I currently have this setup is to have [appname].xml in conf/Catalina/localhost. However, when I redeploy the app, this file gets overridden with an empty context file, and I have to copy the custom one back to the conf/Catalina/localhost directory. I have different database settings, etc. for my test and production servers, and so don't want to put the context file in META-INF in the WAR file, but would like to just keep it in the conf/Catalina/localhost directory. Is this possible?
Is there somewhere better to put the database configuration?
I'd also like to avoid putting the configuration in the server.xml file, although I know this is possible.
Thanks!
I would say look into using maven profiles (one for prod, one for test), and having different resource definitions for each profile. You can keep your common files in src/main/resources and then have a folder for each profile type to keep specific config files in:
src/test/resources
src/prod/resources
Then you can amend your pom to define each profile and its associated resources:
<project>
<profiles>
<profile>
<id>prod</id>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<targetPath>${project.build.outputDirectory}</targetPath>
</resource>
<resource>
<directory>src/prod/resources</directory>
<targetPath>${project.build.outputDirectory}</targetPath>
</resource>
</resources>
</build>
</profile>
<profile>
<id>test</id>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<targetPath>${project.build.outputDirectory}</targetPath>
</resource>
<resource>
<directory>src/test/resources</directory>
<targetPath>${project.build.outputDirectory}</targetPath>
</resource>
</resources>
</build>
</profile>
</profiles>
</project>
finally you can build the war using the -Pprod or -Ptest profile argument to mvn
mvn -Pprod package
Problem is that undeploy removed the webapp specific context.xml file that was installed in Catalina/localhost/.xml
If you don't want to have the file removed, you'll have to just redeploy it, not undeploy/deploy