How to exclude a maven variable (same syntax as ksh variable) - java

i'm facing a sketchy problem, i have a ksh script that gets a ${USER} variable from a configuration file. i can't change the name of the variable, but since it's also the name of an environment variable in UNIX, the value gets replaced by the Maven builder.
Is there a way to exclude this variable from being changed by Maven?
Thanks.
Maven variables : ${var}
ksh variable :${var}

If this file is in src/main/resources and being filtered by the normal Maven resources plugin, you may configure an escape character to prevent this. Add configuration for the resources plugin and define the escape char to use.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version><fillInLatestVersion></version>
<configuration>
...
<escapeString>\</escapeString>
...
</configuration>
</plugin>
Then configure the resources file to escape anything Maven shouldn't replace.
Maven variables : ${var}
ksh variable : \${var}

Related

Maven Archetype: Validate artifactId or groupId

I want to build a Maven archetype that checks whether the supplied artifactId and groupId match a given regex. In this way, I want to enforce the naming conventions of our organisation, e.g. ear files having names ending with -app and all groupIds starting with de.companyname.
Is this possible?
I found that you can check against a regex for requiredProperty
https://maven.apache.org/archetype/archetype-models/archetype-descriptor/archetype-descriptor.html
but the given value is ignored when I build the archetype through eclipse, which could be due to an old version of the maven-archetype-plugin that is used in eclipse (and this is not applicable to "build-in" properties like groupId or artifactId).
This:
<requiredProperties>
<requiredProperty key=.. >
<defaultValue/>
<validationRegex/>
</requiredProperty>
</requiredProperties>
... is the way to define a required property (with defaults and validation). However, IIRC, it was introduced in v3.0.0 of the archetype plugin so perhaps you are using a prior version.
Edit 1: in response to this question "can validationRegex be applied to artifactId and groupId". Yes, it can. It can be applied to any entry in requiredProperties but with this caveat: validationRegex only works for inputs supplied at the command line, so providing a defaultValue or defining a value via a command line parameter (-DgroupId=..., -DartifactId=... ) side steps validation. Here's a concrete example, given the following requiredProperties in archetype-descriptor.xml:
<requiredProperties>
<requiredProperty key="artifactId">
<validationRegex>^[a-z]*$</validationRegex>
</requiredProperty>
<requiredProperty key="groupId">
<defaultValue>COM.XYZ.PQR</defaultValue>
<validationRegex>^[a-z]*$</validationRegex>
</requiredProperty>
</requiredProperties>
The following command: mvn archetype:generate -DarchetypeGroupId=... -DarchetypeArtifactId=... -DarchetypeVersion=... -DgroupId=com.foo.bar will result in com.foo.bar being used for groupId and the user will be prompted to supply an artifactId like so:
Define value for property 'username' (should match expression '^[a-z]*$'): Whatever
Value does not match the expression, please try again: whatever
Define value for property...
So far so good (sort of).
But the following command mvn archetype:generate -DarchetypeGroupId=... -DarchetypeArtifactId=... -DarchetypeVersion=... -DartifactId=whatever will result in COM.XYZ.PQR being used for groupId even though that does not conform to the validationRegex.
Similarly; the following command mvn archetype:generate -DarchetypeGroupId=... -DarchetypeArtifactId=... -DarchetypeVersion=... -DartifactId=WHATEVER will result in COM.XYZ.PQR being used for groupId and WHATEVER being used for artifactId even though those values do not conform to the validationRegex.
So, in summary: the validationRegex works for any requiredProperty (whether its a reserved property - such as artifactId - or a bespoke property) but it only applies to values which are provided interactively and hence setting a default value or supplying a value via a command line parameter side steps validation.
Note: even if you do use validationRegex you might also want to consider using the Maven Enforcer Plugin's requireProperty rule because thes project properties you wan to enforce could be changed after the archetype has been used to create the project. From the docs:
This rule can enforce that a declared property is set and optionally evaluate it against a regular expression.
Here's an example:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>enforce-property</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireProperty>
<property>project.artifactId</property>
<message>"Project artifactId must match ...some naming convention..."</message>
<regex>...naming convention regex...</regex>
<regexMessage>"Project artifactId must ..."</regexMessage>
</requireProperty>
</rules>
<fail>true</fail>
</configuration>
</execution>
</executions>
</plugin>

How do I include maven environment variables in eclipse to war file

I have environment variables in my application.properties like this spring.mail.username=${username}
The ${username} is declare in eclipse environment variable. When I build maven package and install, then deploy it to tcServer. The TC Server does not know ${username}. Another word, the environment variables do not include in the war file during build.
How do I get the environment variable in eclipse to include in war file for deployment?
Using Maven filtering as described in alexbt's answer, is the right approach for including values defined elsewhere. His example touches on including an operating system environment variable. You can extend this to Maven properties also. For example,
<project ...>
<properties>
<spring.mailuser>bob#mycompany.com</spring.mailuser>
</properties>
...
<build>
...
</build>
</project>
defines a Maven properties whose value is retrieved by ${spring.mailuser} and can be used as part
of other Maven configurations or injected as content via Maven filtering. Given this, changing
applicable.properties as follows
spring.mail.username=${spring.mailuser}
will inject the value of the property at build time.
If you wish to have a build-time variable replaced, I would suggest you to use maven filtering:
Have an environment variable (not an eclipse one):
export username=user3184890
Then, in your pom.xml, activate maven filtering on resources (assuming your application.properties is in src/main/resources:
<build>
<resources>
<resource>
<directory>${project.basedir}/src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
...
Also, change your application.properties to this:
spring.mail.username=${env.username}
or
spring.mail.username=#env.username#

How to get name of Maven dependency JAR (not full path) as a pom.xml variable

It looks like it is possible to get the path/to/a/dependency.jar as an expandable variable within a Maven pom.xml: see Can I use the path to a Maven dependency as a property? You can expand, e.g., an expression into a string like /home/pascal/.m2/repository/junit/junit/3.8.1/junit-3.8.1.jar.
What I want instead of the full path to the dependency JAR within my local Maven repository is just the bare name of the JAR, for example junit-3.8.1.jar.
So for example, within my pom.xml, I would like to be able to use a value like ${maven.dependency.junit.junit.jar.name} to expand to junit-3.8.1.jar.
Can I do this, and how?
You can use the maven-antrun-plugin to get the file name of a dependency. Ant has a <basename> task which extracts the file name from a path. As described in Can I use the path to a Maven dependency as a property? the full path name of a dependency is available in ant as ${maven.dependency.groupid.artifactid.type.path}. This enables us to extract the file name with the ant task like this:
<basename file="${maven.dependency.groupid.artifactid.type.path}" property="dependencyFileName" />
This stores the file name in a property named dependencyFileName.
In order to make this property availbable in the pom, the exportAntProperties configuration option of the maven-antrun-plugin needs to be enabled. This option is only available as of version 1.8 of the plugin.
This example shows the plugin configuration for retrieving the artifact file name of the junit dependency:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<phase>initialize</phase>
<configuration>
<exportAntProperties>true</exportAntProperties>
<tasks>
<basename file="${maven.dependency.junit.junit.jar.path}"
property="junitArtifactFile"/>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
No, I'm sorry to say that it isn't possible. So, you have two options before you.
1) modify the maven source code and contribute the modification.
2) write your own plug-in.
I recommend the second option. Writing plug-ins is not that hard. As a philosophical principal, select a frequently-used plug-in which has functionality close to what you want to accomplish. Read and understand the code, and then modify it to do what you desire.
So for your example, you might look at the filter plugin. There's also some interesting syntax going on in the Ant plugin. It allows you to name dependencies and get those jar filenames into the embedded Ant script.
Good luck. :-)
As a more practical alternative, you might just break down and manually code the property value with the exact version number you're using. You're not going to switch the version number that often, right? And this is only one jar you're dealing with, right?

change classpath in Appassembler - Maven Plug-In

I'm using default appassembler configuration for generating execution script:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>appassembler-maven-plugin</artifactId>
<configuration>
<programs>
<program>
<mainClass>SomeMainClass</mainClass>
<name>data-generator</name>
</program>
</programs>
</configuration>
</plugin>
after generating, my execution script contains lines such as:
set CLASSPATH = C:\Program Files (x86)\my-program\bin\\..\repo"\junit\junit\4.10\junit-4.10.jar
The goal is to change this paths to the following:
set CLASSPATH = C:\Program Files (x86)\my-program\bin\..\lib\junit\junit\4.10\junit-4.10.jar
Is there some good way to achieve this?
I've seen there are many optional parameters for this plugin but I'm not sure how to use it.
Could you bring more details to your question?
If you want to change default repository folder name, which is "repo", you can add following to configuration section
<repositoryName>lib</repositoryName>
All of your dependencies will be put to lib folder, so CLASSPATH will be also changed.
If you would like to shorten your CLASSPATH, you may add this option
<useWildcardClassPath>true</useWildcardClassPath>
Please tell me, if it solved your problem.

Environment Variable with Maven

I've ported a project from Eclipse to Maven and I need to set an environment variable to make my project work.
In Eclipse, I go to "Run -> Run configurations" and, under the tab "environment", I set "WSNSHELL_HOME" to the value "conf".
How can I do this with Maven?
You can just pass it on the command line, as
mvn -DmyVariable=someValue install
[Update] Note that the order of parameters is significant - you need to specify any options before the command(s).[/Update]
Within the POM file, you may refer to system variables (specified on the command line, or in the pom) as ${myVariable}, and environment variables as ${env.myVariable}. (Thanks to commenters for the correction.)
Update2
OK, so you want to pass your system variable to your tests. If - as I assume - you use the Surefire plugin for testing, the best is to specify the needed system variable(s) within the pom, in your plugins section, e.g.
<build>
<plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
...
<configuration>
...
<systemPropertyVariables>
<WSNSHELL_HOME>conf</WSNSHELL_HOME>
</systemPropertyVariables>
</configuration>
</plugin>
...
</plugins>
</build>
The -D properties will not be reliable propagated from the surefire-pluging to your test (I do not know why it works with eclipse). When using maven on the command line use the argLine property to wrap your property. This will pass them to your test
mvn -DargLine="-DWSNSHELL_HOME=conf" test
Use System.getProperty to read the value in your code. Have a look to this post about the difference of System.getenv and Sytem.getProperty.
You could wrap your maven command in a bash script:
#!/bin/bash
export YOUR_VAR=thevalue
mvn test
unset YOUR_VAR
For environment variable in Maven, you can set below.
http://maven.apache.org/surefire/maven-surefire-plugin/test-mojo.html#environmentVariables
http://maven.apache.org/surefire/maven-failsafe-plugin/integration-test-mojo.html#environmentVariables
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
...
<configuration>
<includes>
...
</includes>
<environmentVariables>
<WSNSHELL_HOME>conf</WSNSHELL_HOME>
</environmentVariables>
</configuration>
</plugin>
Following documentation from #Kevin's answer the below one worked for me for setting environment variable with maven sure-fire plugin
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<environmentVariables>
<WSNSHELL_HOME>conf</WSNSHELL_HOME>
</environmentVariables>
</configuration>
</plugin>
Another solution would be to set MAVEN_OPTS (or other environment variables) in ${user.home}/.mavenrc (or %HOME%\mavenrc_pre.bat on windows).
Since Maven 3.3.1 there are new possibilities to set mvn command line parameters, if this is what you actually want:
${maven.projectBasedir}/.mvn/maven.config
${maven.projectBasedir}/.mvn/jvm.config
There is a maven plugin called properties-maven-plugin this one provides a goal set-system-properties to set system variables. This is especially useful if you have a file containing all these properties. So you're able to read a property file and set them as system variable.
in your code add:
System.getProperty("WSNSHELL_HOME")
Modify or add value property from maven command:
mvn clean test -DargLine=-DWSNSHELL_HOME=yourvalue
If you want to run it in Eclipse, add VM arguments in your Debug/Run configurations
Go to Run -> Run configurations
Select Tab Arguments
Add in section VM Arguments
-DWSNSHELL_HOME=yourvalue
you don't need to modify the POM
You can pass some of the arguments through the _JAVA_OPTIONS variable.
For example, define a variable for maven proxy flags like this:
_JAVA_OPTIONS="-Dhttp.proxyHost=$http_proxy_host -Dhttp.proxyPort=$http_proxy_port -Dhttps.proxyHost=$https_proxy_host -Dhttps.proxyPort=$http_proxy_port"
And then use mvn clean install (it will automatically pick up _JAVA_OPTIONS).
I suggest using the amazing tool direnv. With it you can inject environment variables once you cd into the project. These steps worked for me:
.envrc file
source_up
dotenv
.env file
_JAVA_OPTIONS="-DYourEnvHere=123"
As someone might end up here changing his global Java options, I want to say defining _JAVA_OPTIONS is a bad idea. Instead define MAVEN_OPTS environment variable which will still be picked up automatically by Maven but it won't override everything like _JAVA_OPTS will do (e.g. IDE vm options).
MAVEN_OPTS="-DmyVariable=someValue"

Categories