In my Maven build I would like to be able to define default values (e.g. for database connection) in pom.xml, but I would like the user to be able to override these without having to modify pom.xml directly.
By way of example, in an Ant build you can define default properties in foo.properties, but Ant will look for overrides for each of these in a foo.$USERNAME.properties. The latter is generally not checked into source control, which eliminates the problem of developers accidentally committing their overrides of the default properties. Does Maven offer a similar facility?
To make the problem a bit more concrete, assume I have the following defined in pom.xml
<properties>
<db.url>jdbc:jtds:sqlserver://10.10.10.10:1433/somedb</db.url>
<db.driver>net.sourceforge.jtds.jdbc.Driver</db.driver>
<db.username>default_user</db.username>
<db.password>secret</db.password>
</properties>
Can a user override these properties without editing the pom.xml directly?
You can specify properties on the command line using -Dpropertyname=value, or the user can specify properties in their .m2/settings.xml.
You can achieve this with build profiles. See Introduction to build profiles for more information.
I used settings.xml to override these properties by adding the following to the <profiles> section
<profile>
<id>override-database-properties</id>
<activation>
<property>
<name>refreshDB</name>
</property>
</activation>
<properties>
<db.schema_name>store_don</db.schema_name>
</properties>
</profile>
In this case the overrides will only take effect if a -DrefreshDB is passed to the mvn command. To activate these overrides every time Maven is invoked also add the following to settings.xml
<activeProfiles>
<activeProfile>alwaysActiveProfile</activeProfile>
</activeProfiles>
If the profile is added to <activeProfiles> then the <activation> element should be removed.
If you don't want to add properties on the command line, but set some settings once (and if you can accept the default being empty strings); you could use environment variables like this:
<something>${env.ENVNAME}</something>
<!-- something will be blank "" unless ENVNAME is set -->
Edit: I've been trying to find a way of defining a default values for ${variable} if the variable is empty/undefined, but I've not found anything, this seems to be missing (the frequent suggestion is to use profiles but it's not quite the same).
I'd prefer if you could just set some environment variables and have sensible defaults so that you could just run mvn clean install (and not the 20-40 character strings I normally use to build our project). If default values is possible I'd love hear how...
BTW, if you're already used to Ant, I've heard that you can call Ant tasks from maven somehow (don't know how, though), maybe you could use that somehow?
Related
I've got a project with Serenity properties file configuration and I want to put a security code before to start the test, so at the beginning when I prepare the test, I clean the value like this:
...
serenity.timeout=1000
secretVariable=
serenity.verbose.steps=FALSE
...
but when I run the test, I want to change the serenity.properties like this:
...
serenity.timeout=1000
secretVariable=24C20-00034D2
serenity.verbose.steps=FALSE
...
So , my question is, is this possible using a java code and/or maven configuration?
If you want to change some non-configuration file settings, I may only provide configuration related to the springboot project, you can set your vm option:
--serenity.timeout=1000
--secretVariable=24C20-00034D2
--serenity.verbose.steps=FALSE
Or you can modify the args parameter of your launch:
String[] arg=new String[3];
arg[0]="--serenity.timeout=1000";
arg[1]="--secretVariable=24C20-00034D2";
arg[2]="--serenity.verbose.steps=FALSE";
This is the method I can think of. I have not tried to use maven to manage these parameter configurations, but I have used maven to manage parameter modules. You can use this method to manage, and it supports .yml and .proerties, I will give you an example, but for the specific usage method, you need to go to the official springboot documentation to find the detailed usage method:
maven:
<!--Configure maven multi-environment development-->
<profiles>
<profile>
<id>enc_dev</id>
<properties>
<profile.active>dev</profile.active>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>enc_dev</id>
<properties>
<profile.active>dev</profile.active>
</properties>
</profile>
</profiles>
application.proerties:
spring.profiles.active=#profile.active#
spring.profiles.group.dev=devMVC,devDB
spring.profiles.group.pro=proMVC
This way you can easily manage the modules you want and do targeted configuration, hope this helps you.
Say, there is a property customProp in the pom.xml in my spring project.
2.4.snap
When I run my project, I can update its value like below
mvn clean install -DcustomProp=newValue
It's working well. It updates the value of customProp with newValue.
But I want to concat newValue with the previous value of customProp. So that the value of customProp will be 2.4.snapnewValue.
How can I do that?
Further, is it possible to replace snap with newValue so that the value of customProp will be 2.4.newValue.
<properties>
<customProp>snap</customProp>
</properties>
<version>2.4.${customProp}</version>
Would this be possible in your situation? Of course, use the correct tag where I'm using <version>.
The best way to approach this might be more like:
<properties>
<customPropPrefix>2.4.</customPropPrefix>
<customProp>snap</customProp>
</properties>
<version>${customPropPrefix}${customProp}</version>
Now you can specify both -DcustomPropPrefix=2.4. and -DcustomProp=newValue.
Rather than build and clean your maven project forcefully it will sure update your maven projectenter image description here
I have a maven project, and in the pom.xml I set properties as such:
<project>
<modelVersion>4.0.0</modelVersion>
<artifactId>myArtifact</artifactId>
<name>SomeProject</name>
<packaging>jar</packaging>
<properties>
<some-system-property>1.9.9</some-system-property>
</properties>
<...>
</project>
I want to pull the some-system-property value from within the java code, similar to
String someSystemPropery = System.getProperty("some-system-property");
But, this always returns null. Looking over StackOverflow, most of the answers seem to revolve around enhanced maven plugins which modify the code - something that's a nonstarter in my environment.
Is there a way to just get a property value from a pom.xml within the codebase? Alternatively, can one get the version of a dependency as described in the pom.xml (the 1.9.9 value below):
<dependencies>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.9</version>
</dependency>
</dependencies>
from code? Either one would solve my needs
Those are Maven properties that apply during the build, not runtime system properties. One typical approach is to use Maven resource filtering to write the value into a properties file in the target directory.
Maven properties and not system properties.
Generally you should set the system property for a maven plugin that is triggering the execution:
surefire for unit tests,
exec for execution,
jetty or similar for starting a web container
There is also properties maven plugin than can set properties:
http://mojo.codehaus.org/properties-maven-plugin/set-system-properties-mojo.html
Property values are accessible anywhere within a POM by using the notation ${X}, where X is the property, not outside. All properties accessible via java.lang.System.getProperties() are available as POM properties, such as ${java.home}, but not the other way around. So for your java code, it will need to scan the pom.xml as a xml parsing use case, but not sure why you want to do it.
I have a project that consists of several Maven modules which are all children of a parent module.
I have the parent set up to use checkstyle and the child modules all inherit this behaviour correctly. I would like all the child modules to use the parents suppression file defined in its plugin.
I define a property checkstyle.suppression which is used in the checkstyle plugin
<properties>
<checkstyle.suppressions>${basedir}\src\checkstyle\suppressions.xml</checkstyle.suppressions>
</properties>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>2.2</version>
<configuration>
<configLocation>config/sun_checks.xml</configLocation>
<suppressionsLocation>${checkstyle.suppressions}</suppressionsLocation>
<suppressionsFileExpression>${checkstyle.suppressions}</suppressionsFileExpression>
</configuration>
</plugin>
</plugins>
Which works fine for the parent but all the child modules try to find the file in their basedir which does make sense.
I am sure there must be a simple solution I am missing but is there a way to define this location so that all the child modules will use the parent location without hard coding it?
The answers above are dangerous. I maintain that each project should be self contained, so referring to files external to it is going to break a build sooner or later. Checkstyle can take a url for the file but that means you can't build offline. A better approach is to package your file (can also add pmd.xml) into a jar and then add that jar to the classpath of the checkstyle (or pmd) plugin. I have an example of it here and more about overridding a plugin classpath here
The plugin's documentation mentions a similar use case here:
http://maven.apache.org/plugins/maven-checkstyle-plugin/examples/multi-module-config.html
Have you tried defining the property like this in the parent pom or redefining it in the childrens?
<properties>
<checkstyle.suppressions>${parent.project.basedir}\src\checkstyle\suppressions.xml</checkstyle.suppressions>
</properties>
If the parent isn't going to run checkstyle, you might just be able to rewrite it to
<properties>
<checkstyle.suppressions>..\..\src\checkstyle\suppressions.xml</checkstyle.suppressions>
</properties>
Or something like this. Or you could put something in settings.xml to point everything to an system wide config directory.
While it might not be recommended, you can have use a boot-strap or set-up project or task put a copy of the suppressions.xml file to a location specified by a property in settings.xml and then always refer to it by that locations.
I would really like to make maven write the "target" folder to a different device (ramdisk), which I would normally consider to be a different path. Is there any maven2-compliant way to do this ?
I am trying to solve this problem on windows, and a maven-compliant strategy would be preferred.
If you happen to have all of your projects extending a corporate parent pom, then you could try adding Yet Another Layer of Indirection as follows:
Corporate POM:
<build>
<directory>${my.build.directory}</directory>
</build>
<properties>
<!-- sensible default -->
<my.build.directory>target</my.build.directory>
</properties>
In your settings.xml:
<properties>
<!-- Personal overridden value, perhaps profile-specific -->
<my.build.directory>/mnt/other/device/${project.groupId}-${project.artifactId}/target</my.build.directory>
</properties>
If the local POM definition takes precedence over the settings.xml definition, then you could try omitting the default value at the cost of having every Maven instance in your control (developers, build machines, etc) specify ${my.build.directory} in its settings.xml.
Actually, Maven is not as constrained as everybody thinks, all the POMs are extended of one Super POM in which is defined the name of the target folder
<build>
<directory>target</directory>
<outputDirectory>target/classes</outputDirectory>
<finalName>${artifactId}-${version}</finalName>
<testOutputDirectory>target/test-classes</testOutputDirectory>
.
.
.
</build>
Of course you can overwrite with any value you want, so just go ahead and change the <directory /> element (and other related elements) in your POM
just in case if you want to fix this for your own Maven3 and not touch anything in the project, locate file:
$MAVEN_HOME/lib/maven-model-builder-3.X.Y.jar
and update super-pom inside
org/apache/maven/model/pom-4.0.0.xml
changing line
<directory>${project.basedir}/target</directory>
in
<directory>/tmp/maven2/${project.groupId}-${project.artifactId}/target</directory>
so next time when you will build any maven project - it will put all classes under /tmp/