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

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#

Related

How to get file location for #PropertySource in Spring from Maven property

I have 2 properties files stored in resources folder: qa.properties and dev.properties.
I specified Maven property 'environment', this is the name of property file that should be loaded.
<properties>
<environment>qa</environment>
</properties>
I want to load required properties according to the maven variable, but #PropertySource doesn't see maven variables. How to pass 'environment' property from Maven to the #PropertySource?
#Configuration
#PropertySource("classpath:${environment}.properties")
public class Config {
#Autowired
private Environment env;
public Environment getEnv() {
return env;
}
public void setEnv(Environment env) {
this.env = env;
}
}
Maybe you can use profile-specific properties like application-qa.properties for this purpose and activate it in application.properties with spring.profiles.active=qa here more https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-profiles.html
Don't do this at build time using a Maven property. This approach forces you to build an artifact for every environment which is not a good practice.
A better approach is to build only one artifact and/or application to be deployed in any environment (qa, stage, load-test, prod, ....)
One way is to name your property files application-test.properties, application-xxxxx.properties and run you application as:
java -Dspring.profiles.active=qa myapp.jar
No need for the Config class you described earlier if you follow this approach.
This should get you started. Notice you would have to include property files for different environments but this could also be worked out. Take a look at the 12 factor-app.
For this purpose you have to specify your environment property as System property. Maven Surefire Plugin can help you with that:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${surefire.version}</version>
<configuration>
<systemPropertyVariables>
<environment>QA</environment>
</systemPropertyVariables>
</configuration>
</plugin>

Run maven project that has profile with junit runner

My pom.xml has <systemPropertyVariables> and <profiles>. Right now if I want to run it as a maven build i am using -DXXX for system property variables and -PXXX for profiles in the goal.
Now I would like to run this as JUnit test in eclipse. I found that system property variables can be given in VMArguments.
Now the problem is how to access this profile. Here is how my profile looks like
<profile>
<id>devqa</id>
<build>
<resources>
<resource>
<directory>src/main/resources/devqa</directory>
</resource>
</resources>
</build>
</profile>
I have a file in the resource location and im accessing it in my test
File testfile = new File(this.getClass().getResource("/config.properties").toURI());
I tried to give this in Active Maven Profiles but it didn't work. How to make this work
Add the resource path src/main/resources/devqa to junit run configuration class path using add projects widget. It may work.

how to get property value from pom.xml?

I have added a node in my pom.xml:
<properties>
<getdownload-webapp.version>1.5</getdownload-webapp.version>
</properties>
how could I get this 1.5 value in code?
String version = System.getProperty("getdownload-webapp.version"); // output version = null
This code gave me null while running(
ps: there is no settings.xml in this project
So you have a property like this.
<properties>
<getdownload-webapp.version>1.5</getdownload-webapp.version>
</properties>
Create a file as follows in your Maven project.
src/main/resources/project.properties
Or as follows if it is for tests only.
src/test/resources/project.properties
Add this line inside the new file. Please note that you should not prefix with "properties" (e.g. don't write "properties.getdownload-webapp.version").
version=${getdownload-webapp.version}
Note that you can also add flags like this to the file.
debug=false
If not already done, you have to enable Maven filtering for your project. It is the feature that will look for placeholders inside the files of your project to be replaced by values from the pom. In order to proceed, you need add these lines inside the <build> tag of your pom.xml file. This is how to do with src/main:
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
...
And here is how to do for src/test:
<build>
<testResources>
<testResource>
<directory>src/test/resources</directory>
<filtering>true</filtering>
</testResource>
</testResources>
...
Finally, in your source code (MyClassName.java), add a block like
Properties props = new Properties();
props.load(MyClassName.class.getClassLoader().getResourceAsStream("project.properties"));
String version = props.getProperty("version");
You can add as many variables as you want to the project.properties file and load each one using this method.
The mechanism chiefly in charge to transfer Maven properties to Java application is provided by the Maven Resource Plugin
The plugin is part of the Maven Super Pom and executed during the process-resources phase of the Jar Default Lifecyle. The only thing you have to do is to active filtering.
This will replace any placeholders, e.g. ${my.property} in any of the files in src/main/resources with the corresponding property from your pom, e.g. <property><my.property>test</my.property></property>
How you make this property then available to your Java application is up to you - reading it from the classpath would work.
I assume you want to get it in the code to check something right? You can use filtering from maven that will inject the value in the source code, similar to the filtering option
http://mojo.codehaus.org/templating-maven-plugin/
String version = project.getProperties().getProperty("getdownload-webapp.version");
Where project is of type MavenProject

How to use a single checkstyle suppression file in Maven for all modules

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.

Can I move maven2 "target" folder to another device?

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/

Categories