read Maven variable from properties file using profile - maven

I want to read a maven variable for configure a build plugin from a properties file. It's not needed in and further project files e.g. context files.
1) made a profile (it works, can use mvn ... -P private)
<profile>
<id>private</id>
<properties>
<env>private</env>
</properties>
</profile>
2) created the filter file with this content (it works)
foo.path=/home/foo/path
3) try to configure the plugin (does not work)
<build>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>foo-plugin</artifactId>
<version>${foo-plugin.version}</version>
<configuration>
<!--<fooPath>home/foo/path></fooPath> that works -->
<fooPath>${foo.path}</fooPath> <!--works not -->
</configuration>
...
</build>
Thx a lot

The name of your property is 'env' but you don't use env anywhere in your configuration.

When Maven docs mention "filter files" they usually mean a file used when processing resources (i.e. copying resources from /src/main/resources to target/classes). As far as I know the properties in those files aren't used for plugin configuration out-of-the-box. I have used the Codehaus properties-maven-plugin:read-project-properties goal do do what you are attempting. Make sure you bind the goal to the lifecycle before any plugins that need the properties for config.
Also, see this answer; you may load properties used to configure other plugins, but not to configure core Maven project elements.

Related

Could i use maven profile to swith between different value application.properties

I have application-prod.yml application-dev.yml, and application.properties which containing just one line code like below
spring.profiles.active=dev
for maven production build, it should use spring.profiles.active=prod , then it will build with application-prod.yml, for development build, it should use spring.profiles.active=dev, then maven
will use application-dev.yml to build
could I use pom.xml's different profile to do switch for this value switch in applicaiton.properties?
You can use a Maven property for this, reference it in your yml file (with ${...}) and filter the resource (i.e. the yml file) with the maven resources plugin.
It seems that what you're after is "externalized configuration". According to the excellent 12factor guidelines, it is best not to keep such config inside your code-repository.
Refer to the relevant section in the Spring Boot manual to see which options you have (and there are many). What it comes down to is that you provide your application.yml/properties file on the filesystem and your application will read it from there, rather than from the classpath.
Also, note that spring-profiles are not meant to be used to distinguish between development environments, but rather to put the application in different functional modes (e.g. to enable or disable specific features).
If you want the content of your properties file changed at build time, then you can use Maven filtering. Maven filtering allows to replace a placeholder in your properties (or yaml) file by values from Maven properties.
Assuming you have a property in your POM called targetEnv, which might have either the value dev or prod (depending on the active Maven profile), then you can refer it in your properties file (or yaml file) by using the following syntax :
spring.profiles.active=#targetEnv#
However, if you want to follow Spring Boot recommandations, it is better to enable and disable the Spring profiles by the means of environment variables in your target environment. For instance, you can use an environment variable spring.profiles.active with the desired value and it will override the value in your properties file.
You need to define a custom property in each of your Maven profiles and set their values to match with suffixes of corresponding properties files that you want to load with a particular profile.
<profile>
<id>dev</id>
<properties>
<activatedProperties>dev</activatedProperties>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>release</id>
<properties>
<activatedProperties>release</activatedProperties>
</properties>
</profile>
Next, in the build section of the same file, configure filtering for the Resources Plugin. That will allow you to insert properties defined in the previous step into any file in the resources directory, which is the subsequent step.
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
…
</build>
Finally, add the following line to the application.properties.
spring.profiles.active=#activatedProperties#
For more details, please see spring boot properties per maven profile
For official guide to load from external configLoad from external Config

Using multiple JDK on the same machine for maven

I have to build java projects for different java versions. I'm using maven. I would like to specify all JDK locations in one configuration file (probably settings.xml) and then maven should choose correct one based on maven-compiler-plugin configuration specified in the pom and use compiler and standard library from this JDK to build project. Is it possible? I understand that I can use something like
JAVA_HOME=jdk6path mvn package
but it's not convenient.
Yes its possible. In settings.xml define properties like this:
<properties>
<java.home.1.4>C:\Program Files\Java\jdk1.4</java.home.1.4>
<java.home.5>C:\Program Files\Java\jdk1.5</java.home.5>
<java.home.6>C:\Program Files\Java\jdk1.6</java.home.6>
</properties>
Then in your POM file specify the properties
<compiler.source>1.6</compiler.source>
<compiler.target>1.6</compiler.target>
<compiler.compilerVersion>1.6</compiler.compilerVersion>
<compiler.jdk>${java.home.6}</compiler.jdk>
Then int he Maven compiler plugin pass in the executable:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${compilerPluginVersion}</version>
<configuration>
<source>${compiler.source}</source>
<target>${compiler.target}</target>
<compilerVersion>${compiler.compilerVersion}</compilerVersion>
<executable>${compiler.executable}</executable>
</configuration>
</plugin>
You then control which is used by the properties. You can also set up different profiles in the POM with different property values to allow you to run the build with different versions without any change required to the pom.

How does IntelliJ's Maven filtering support work?

I have noticed when you configure a Maven project to use property filtering the property filtering seems to also work during a non-maven IntelliJ "make". This means the IntelliJ run configurations for Jetty/Tomcat/GWT/Glassfish will still honour your maven resource filtering.
So if I add this to my pom.xml:
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>**/*.properties</include>
<include>**/persistence.xml</include>
</includes>
</resource> ....
It should filter any properties in my properties and peristence.xml files before any intellij run configurations start. This is very usefull for swapping in JDBC references or filesystem parameters.
The only problem I am having is that IntelliJ only seems to honour filtering in src/main/resources even if I change pom.xml to have a second entry for other directories (ie:src/integrationtest/resources).
This all seems to be "automagical". So how does it work and where (if anywhere) can I configure it?
IntelliJ IDEA's Make features are capable of filtering Maven resources. However, IntelliJ IDEA yet does not support filtering web resources.
source: http://www.jetbrains.com/idea/webhelp/maven.html#compile
No further details about this support in whole intellij webhelp though, so I guess it should work just like maven's process-resources phase does.
The problems you are having can be caused by the fact that directory src/integrationtest/resources doesn't follow maven conventions.
Maybe it will work if you:
make it src/test/resources/integrationtest/
or
configure maven to respect src/integrationtest as test sources (but if integrationtest isn't well-known convention it will be violation of maven's COC rule)
or
make it another maven (sub)module, if you want to emphasize isolation of integrationtest
As for filtering directories different that src/main/resources: filtering src/main/webapp/META-INF worked out-of-a-box for me.
(Maven 3.0.4, Intellij 12.1.4)
Good news, looks like the issue will be fixed in 13.1
http://youtrack.jetbrains.com/issue/IDEA-25934
EDIT: Sorry if not clear enough, the bug case is just marked as "fixed" with no further explanation...
But I tested in 13.1 EAP version (build 134.1445) and while previously IntelliJ would overwrite the resources, it now preserves the web resources filtered by Maven.
Intellij (I'm using 14.1) does allow you to define custom Ant tasks as pre-/post-processing during artifact build.
Go to Project Structure -> Artifacts -> {select artifact} -> {Pre-processing|Post-processing} tabs.
So, for example, I can use the following simple task to simulate resource filtering in cases where it doesn't work out of the box:
<target name="filter" depends="clean">
<copy todir="${maven.build.dir}/${maven.build.finalName}">
<fileset dir="${maven.build.resourceDir.0}"/>
<filterset begintoken="${" endtoken="}">
<filter token="project.version" value="${project.version}"/>
</filterset>
</copy>
</target>
Don't forget to define a default profile
<profiles>
<profile>
<id>development</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
...
</properties>
</profile>
</profiles>

I can't get maven to use properties defined in ~/.m2/settings.xml?

I am using ~/.m2/settings.xml to store a number of property names used throughout the pom.xml files in my project. If I make the XML invalid (by adding another < for example), maven immediately generates an error, saying that it cannot parse that file. If I leave the XML valid, settings in my appBeans.xml file do not pick of references to properties defined in settings.xml.
Has anyone experienced this problem? I am sort of at my wits end here.
Reflecting properties from Maven configurations works by resources filtering.
Make sure your settings.xml, project pom and the target xml file contain correct configurations and reside in correct places.
If I understood correctly, you want to store a property name and value in the settings.xml so the props can be used in your project files. I'll provide a working example:
Define a default profile and properties in settings.xml:
<profiles>
<profile>
<id>default</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<someProp>Value</someProp>
</properties>
</profile>
</profiles>
Define resource folder's filtering=true in pom.xml:
<build>
<resources>
<resource>
<directory>${basedir}/src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
Define the property in the xml file (that resides in the src/main/resources folder):
...
<element>${someProp}</element>
...
After this you should see the filtered result e.g. in target/classes/appBeans.xml.
Bear in mind that if you're using Eclipse & m2eclipse or similar plugin, it probably won't start using the updated settings.xml without restarting Eclipse and it's automatic build will sometimes overwrite your files in the target folder. I'm talking from experience here :)
Maven properties do not get reflected in miscellaneous XML files.
If you add one of these properties to the <properties/> element of the specific pom that runs the specific plugin that reads allBeans.xml, does that work? I believe that it will not, and your problem will turn out to be adding to the <configuration/> for the plugin to pass the maven properties to it.
If you edit your question to show the plugin that processes appBeans.xml I can make this more specific.

Where should I put application configuration files for a Maven project?

I'm using the Maven Application Assembler plugin to generate stand-alone executables from my Java project. The application reads in configuration files, including Spring files. The Application Assembler plugin has an option (activated by default) to add a etc/ directory to the application's classpath, but what should I do to have the plugin copy my configuration files to this directory?
Or more generally, where is in Maven the kosher location for application configuration files that should NOT be packaged in the artifact?
You can also use resource filtering:
http://maven.apache.org/guides/getting-started/index.html#How_do_I_filter_resource_files
turn on filtering:
...
<build>
...
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
...
</build>
...
make a file under src/main/resources like: application.properties
application.properties
configprop.1=${param1}
configprop.2=${param2}
Then setup a profile and set some properties perhaps in a settings.xml
that sets different properties depending on if this is a dev or production build.
see: http://maven.apache.org/guides/introduction/introduction-to-profiles.html
I have different properties set depending on if this is the build server, dev or a production deployment
mvn -Denv=dev || mvn -Denv=dev-build || mvn -Denv=production
The maven link has a pretty good description.
For folks who have come to this more recently there is, since version 1.1 of the Application Assembler Plugin, the optional parameters configurationSourceDirectory and copyConfigurationDirectory. Please find them in an example POM.xml extract below:
<configuration>
<!-- Set the target configuration directory to be used in the bin scripts -->
<configurationDirectory>conf</configurationDirectory>
<!-- Copy the contents from "/src/main/config" to the target
configuration directory in the assembled application -->
<copyConfigurationDirectory>true</copyConfigurationDirectory>
<!-- Include the target configuration directory in the beginning of
the classpath declaration in the bin scripts -->
<includeConfigurationDirectoryInClasspath>
true
</includeConfigurationDirectoryInClasspath>
...
</configuration>
More information is here
You could try the maven assembly plugin. I used it in conjunction with the appassembler plugin.
Configure appassembler to point to whatever name you want for your configuration directory, if you don't want 'etc'. The assembly plugin assembles everything in its own output directory, so I configure the assembly plugin to copy the bin and repo dirs from the appassembler directory into its output dir, then I have it copy the config files (mine are in src/main/config) into the expected config dir. There is some duplication in this, because you are copying the appassembler outputs, but that didn't really bother me.
So what you have after executing the assembly plugin is your bin, repo, and config dir are all peer directories under the assembly output directory. You can configure it to have a different structure if you prefer, I just wanted mine to mirror the appassembler structure.
The nice thing is that you can also configure the assembly plugin to change your binaries to executables, which I could't see how to do with appassembler. And, if you then bind appassembler:assemble and assembly:single goals to the package phase, all you have to do is 'mvn package', and it assembles everything.
I don't know if I understand you correctly. But what I have done in the past for a project where I needed to copy configuration files, is use the Maven AntRun plugin. What I did is execute the plugin in the process-resources phase and copied my configuration files to the specified directory using the Ant copy task. The Assembler plugin executes in the package phase so it should pick up your configuration files if you put it in the right place. Hope this answers your question a little bit.
I had been looking for an answer to what I think is your question, or at least a very similar question. Maven allows you to specify directories for resources using the maven-resources-plugin. I have a few configuration files in one of my resource directories. I've noticed that by putting copies of those files in the etc/ directory that you mention (which is at the beginning of my CLASSPATH) I can change values in those files for use at run time. I then wanted to have that etc/ directory created with copies of everything from my resource directory by default. The copy-resources goal from the maven-resources-plugin allowed me to do that. This stanza from Examples > Copy Resources on the left sidebar (I'm limited to 2 links in this post) is what did it for me:
<project>
...
<build>
<plugins>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>copy-resources</id>
<!-- here the phase you need -->
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/target/extra-resources</outputDirectory>
<resources>
<resource>
<directory>src/non-packaged-resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
...
</build>
...
</project>

Resources