how to perform task for different profiles using maven - java

I am new to Maven.
I want to perform database connection for different users so my problem is that where I should provide this JDBC connection and how to provide this connection for different users?
I know how to provide profiles for different users but where should I perform database connection and how it get invoked?

Best approach would make your database connection properties (like username/password, url, etc) external. Within a profile you could than define per user the values for the properties and use the maven resource filtering to set them.
Within your maven project you would for example have a config directory (in src/config/settings.prp) which for example contains the following entries:
userName = ${userName}
password = ${password}
db-driver = ${dbDriver}
db-url = ${dbUrl}
Within the pom you would have
<project ...>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.7</version>
<executions>
<execution>
<id>filter-db-settings</id>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/config</outputDirectory>
<resources>
<resource>
<directory>${project.basedir}/src/config</directory>
</resource>
<filtering>true</filtering>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<plugins>
</build>
<profiles>
<profile>
<id>user-A</id>
<properties>
<userName>userA</userName>
<password>secret</password>
<dbDriver>com.driver.db</dbDriver>
<dbUrl>jdbc://db-url</dbUrl>
</properties>
</profile>
<profiles>
</project>
The plugin will filter the files in src/config and replace the maven placeholders by the values as specified within your profile. Since the profile contains a password you could move it to your settings.xml so that it is not checked in with the project itself possibly exposing the password to unwanted parties.
WARNING: Haven't verified the plugin above so might contain small mistakes.
Best practice it to put the property file NOT within the generated artifact. By doing this you get the freedom to use the same artifact fro different users and the only thing you need to change are the properties in the external property file, (which will be given to user beside the artifact).
The following article explains how you can externalize the properties with spring Externalized Configuration.

Related

Versions Maven Plugin rules that are inheritable

When running mvn versions:display-dependency-updates for the Version Maven Plugin I see lots of things like this:
[INFO] org.slf4j:slf4j-api ........................... 1.7.36 -> 2.0.0-alpha7
But just because I'm not using the alpha version of a later version doesn't mean I'm not using the latest available release version. Another Stack Overflow answer indicated that I can set up a rules.xml file to ignore versions like *.-alpha*, putting something like this in my POM:
<configuration>
<rulesUri>file:///${project.basedir}/rules.xml</rulesUri>
</configuration>
My question: is this rules.xml file inheritable? If I put it in a separate project in a parent POM of <packaging>pom</packaging>, published to Maven Central, will the child POMs pick it up? Or will the child projects look for a rules.xml file in the child project directory?
I want to configure the versions-maven-plugin in the parent POM (as I do already) and run mvn versions:display-dependency-updates on any child POM or descendant POM. How can I set up the ignore rules in the parent POM so that these version ignore rules will be picked up when I check for dependency updates in a child POM? (Is there no way to include the rule within the POM itself?)
Or will the child projects look for a rules.xml file in the child project directory?
Yes, if you define the rules.xml file via ${project.basedir} it will resolve to the current local base directory of the child project. I've verified this with a simple parent-child pom setup. So that will not work, unless you duplicate the rules file in every project.
If you wish to include the plugin configuration and ruleset in the parent pom without duplicating the rules file, you have two options:
If you have your ruleset xml file hosted at, for example, http://www.mycompany.com/maven-version-rules.xml then the following configuration in your corporate pom would ensure that all projects use this rule set.
<configuration>
<rulesUri>http://www.mycompany.com/maven-version-rules.xml</rulesUri>
</configuration>
or
You can provide your ruleset xml file also within a jar, if you want to distribute your ruleset xml as Maven artifact. Therefore you have to declare the containing jar as direct dependency of the versions-maven-plugin and to use classpath as protocol.
<configuration>
<rulesUri>classpath:///package/foo/bar/rules.xml</rulesUri>
</configuration>
<dependencies>
<dependency>
<groupId>com.mycompany</groupId>
<artifactId>version-rules</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
Source:
https://www.mojohaus.org/versions-maven-plugin/version-rules.html
The configuration in the pom only has rudimentary includes and excludes filters. Those will allow you to exclude any dependency as a whole, but not specific update versions. As far as i can tell from the available documentation there is no way to define version rules in any other way.
See
https://www.mojohaus.org/versions-maven-plugin/examples/advancing-dependency-versions.html
Update 09-2022
In the github ticket we found in the comments we can see the following update:
It looks like a feature like this has recently been implemented by #369. Please see #318 where it's possible to provide inclusion and exclusion filters for determining which dependency patterns will be considered. Thanks to that, you can rule out patterns such as .*-beta. or .*_ALPHA, albeit not using regexp, but simple asterisk wildcards.
This will land in today's release (2.12.0).
This will add the following features:
Version 2.12.0 will introduce new arguments: dependencyIncluded, dependencyExcludes, dependencyManagementIncludes, dependencyManagementExcludes.
With the following example configuration in pom.xml given:
<profile>
<id>display-dependency-updates</id>
<build>
<plugins>
<plugin>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${project.version}</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>display-dependency-updates</goal>
</goals>
<configuration>
<dependencyIncludes>org.apache.maven.*:doxia*</dependencyIncludes>
<dependencyManagementIncludes>com.puppy*:*</dependencyManagementIncludes>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
This will also be implemented for filtering plugin and pluginManagement, but that will probably be added in a later release:
So, I've just added the missing plugin- and plugin management filtering which works likewise. I really doubt it will land into today's release though.
Pasting my answer here from Github, because I think it might benefit others.
Provided you have a directory called rules-test in your project containing the rules template file:
<ruleset comparisonMethod="maven"
xmlns="http://mojo.codehaus.org/versions-maven-plugin/rule/2.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://mojo.codehaus.org/versions-maven-plugin/rule/2.0.0
https://www.mojohaus.org/versions-maven-plugin/xsd/rule-2.0.0.xsd">
<ignoreVersions>
<ignoreVersion type="regex">${ignoredVersions}</ignoreVersion>
</ignoreVersions>
</ruleset>
Then, in your main project, create the following profile:
<profile>
<id>rules-test</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<resources>
<resource>
<directory>rules-test</directory>
<filtering>true</filtering>
</resource>
</resources>
<outputDirectory>${project.basedir}</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>versions-maven-plugin</artifactId>
<version>2.12.0</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>display-dependency-updates</goal>
</goals>
<configuration>
<rulesUri>file://${project.basedir}/compiled-rules.xml</rulesUri>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
If you then execute the following Maven target:
mvn -P rules-test "-DignoredVersions=.*-(M\d*|.*-SNAPSHOT)" clean validate
then you will get a dependencies report using the filter in the -DignoredVersions argument (filtering out both *-M* and *-SNAPSHOT).
And if you put your ignoredVerions property in your project instead of passing it as a -D argument, then it will be inheritable!

How do I change frontend folder location and configure it in Vaadin14?

How do I change the default frontend folder location in a maven Vaadin 14 project from ${project.basedir}/frontend to ${project.basedir}/src/main/frontend?
Also, Vaadin plugin outputs frontend folder in maven build output directory instead of the war exploded directory, where I would expect it to be.
How do it make it to work since I did not map this folder into my web.xml file?
How do I make it put frontend folder into the war archive and see which configuration it is using to make the compiled front end visible to my application?
Vaadin uses the frontend folder differently in both dev and production modes. In production it builds the frontend using the build-frontend goal. Vaadin Maven Plugin don't have a proper documentation, the best place I found explaining what each goals do is here: https://vaadin.com/docs/v14/flow/production/tutorial-production-mode-advanced.html. This page explains that build-frontend is responsible for building and putting the frontend processed into WEB-INF\classes\META-INF\VAADIN\build when in production mode.
Dev mode is very different, development instructions explains that if you don't use an embedded server you should configure your IDE to run prepare-frontend goal before deployment: https://vaadin.com/docs/v14/flow/workflow/run-on-server-intellij.html. But prepare-frontend just creates the empty frontend folder into target, how does it find frontend files if the folder is empty and nothing is copied to the war exploded folder? Answer: when you run the application, Vaadin has a DevModeInitializer that creates the file generated-flow-imports.js into target/frontend, which refer directly to the project source files, so that any modifications made at them may be reflected immediately, and that's why there is no need of any configuration in web.xml or context listener.
Dev mode make kind of a hack with frontend folder to make development smoother, and prod mode compile everything from frontend into a minified file served by the Vaadin servlet, so only in prod mode frontend goes into the war file. In the first case, prepare-frontend must be used, in the second, build-frontend must be used also. So, in order to modify the frontend folder location, one must change the plugin configuration in those two goals:
<plugin>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-maven-plugin</artifactId>
<version>${vaadin.version}</version>
<executions>
<execution>
<goals>
<goal>prepare-frontend</goal>
</goals>
</execution>
</executions>
<configuration>
<frontendDirectory>${project.basedir}/src/main/frontend</frontendDirectory>
</configuration>
</plugin>
<profiles>
<profile>
<!-- Production mode is activated using -Pproduction -->
<id>production</id>
<properties>
<vaadin.productionMode>true</vaadin.productionMode>
</properties>
<dependencies>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>flow-server-production-mode</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>build-frontend</goal>
</goals>
<phase>compile</phase>
</execution>
</executions>
<configuration>
<frontendDirectory>${project.basedir}/src/main/frontend</frontendDirectory>
</configuration>
</plugin>
</plugins>
</build>
</profile>
That way, the modification will work in both dev and production mode.

Maven: profile-based properties used in plugins section

I would like to mention I am relatively new in Maven configurations.
My situation:
I use Maven 3.0.5 to build J2E application
the application is deployed in four different environments: local, dev, test and prod
I use maven profiles to configure environment-specific configurations
I have defined these configurations in properties files in the file system.
This is the file system for those:
<my-project-root>
---profiles
------local
---------app.properties
------dev
---------app.properties
------test
---------app.properties
I load the corresponding property file with the following logic in my pom.xml:
<profiles>
<profile>
<id>local</id>
<!-- The development profile is active by default -->
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<build.profile.id>local</build.profile.id>
</properties>
</profile>
<profile>
<id>dev</id>
<properties>
<build.profile.id>dev</build.profile.id>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<build.profile.id>prod</build.profile.id>
</properties>
</profile>
<profile>
<id>test</id>
<properties>
<build.profile.id>test</build.profile.id>
</properties>
</profile>
</profiles>
<build>
<finalName>MyProject</finalName>
<plugins>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
<resource>
<directory>profiles/${build.profile.id}</directory>
</resource>
</resources>
</build>
With this configuration I can use the respective properties for my current profile almost everywhere. Everywhere, but the <plugins> section. I would pretty much like to load e.g, my database url or credentials from such properties files, but if I include them in the app.properties they are not evaluated in the plugins section (e.g. I get value of ${endpoint} as database endpoint).
How do I get the properties loaded from files for the profile accessible in the <plugins> section?
PS: Yes, if I add those properties directly in the pom.xml as properties under <profiles> tag, they are accessible, but I would rather keep my passwords off the pom.
I was able to do what I wanted to do. I used properties-maven-plugin linked from, say this answer.
What I did was the following:
I added the properties-maven-plugin to read the files I needed loaded
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-maven-plugin</artifactId>
<version>1.0-alpha-2</version>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>read-project-properties</goal>
</goals>
<configuration>
<files>
<file>profiles/${build.profile.id}/app.properties</file>
</files>
</configuration>
</execution>
</executions>
</plugin>
Regretfully, here I was not able to make the plugin read all property files in a directory, but I find this good enough.
I also needed to remove the error the plugin definition above gave for me in Eclipse (Plugin execution not covered by lifecycle configuration). To do thatI followed the instructions from the following post.
With those steps the properties I needed became available for the plugins, that used them.
Note: actually the properties get loaded after the compile maven command, but this is good enough for me, as all my property-dependant goals are to be executed after compile goal in sequence of goal calls in all my cases.

MAVEN , How can remove JSP page based on environment

I am building one war file using mvn clean install -Dlifecycle=dev . so i have variable lifecycle.
Now my requirement is , when i create build file for UAT/PROD it must exclude one jsp(index.jsp) from package .My jsp is in webApps directory parallel to resources.
Using profile only for one page filtering is not good idea i think.
Appreciate any help .
It starts with one JSP. Next is a customized CSS. Then different DB properties...
A profile is the way to go. Just create one, set its activation to the value of the variable, create another source folder with the JSP and add it to the resources in the profile.
So:
Create a folder src/dev/webapp in your project folder (so it is parallel to src/main/webapp)
Add a profile to your pom.xml that configures the war plugin
<profiles>
<profile>
<activation>
<property>
<name>lifecycle</name>
<value>dev</value>
</property>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.2</version>
<configuration>
<webResources>
<resource>
<directory>src/dev/webapp</directory>
</resource>
</webResources>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
This copies the resources from src/dev/webapps into the merged target folder when the variable lifecycle is set to dev.
Even if those are quite some lines of XML for copying a single file I think it is not a good idea to do it different (e.g. with a plugin that deletes files) when using Maven. While you can customize Maven builds so they aren't recognizable any more, the whole idea is to use the conventions so others can easily read the process.

pass a java parameter from maven

I need to execute some tests with maven, and pass a parameter from the command line.
My java code should get the parameter as:
System.getenv("my_parameter1");
and I define the parameter in the pom.xml file as the example below:
(and latter, I'd modify the pom.xml to get the parameter from the common line mvn clean install -Dmy_parameter1=value1)
but it does not work; System.getenv("my_parameter1") returns null.
how should I define the parameter in the pom.xml file?
pom.xml
<project>
...
<profiles>
<profile>
<properties>
<my_parameter1>value1</my_parameter1>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<id>slowTest</id>
<phase>test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<skip>false</skip>
<includes>
<include>**/*Test.java</include>
<include>**/*TestSlow.java</include>
</includes>
<properties>
<my_parameter1>value1</my_parameter1>
</properties>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
System.getenv() reads environment variables, such as PATH. What you want is to read a system property instead. The -D[system property name]=[value] is for system properties, not environment variables.
You have two options:
If you want to use environment variables, use the OS-specific method of setting the environment variable my_parameter1 before you launch Maven. In Windows, use set my_parameter1=<value>, in 'nix use export my_parameter1=<value>.
You can use System.getProperty() to read the system property value from within your code.
example:
String param = System.getProperty("my_parameter1");
In you surefire plugin configuration, you can use:
<configuration>
<systemPropertyVariables>
<my_property1>${my_property1}</my_property1>
</systemPropertyVariables>
</configuration>
Which takes the Maven property _my_property1_ and sets it also in your tests.
More details about this here.
I'm not sure if system properties from Maven are automatically passed to tests and/or whether fork mode affects whether this happens, so it's probably a good idea to pass them in explicitly.
Use
${env.my_parameter}
to access the environment variable in the pom.xml.
You can use the help plugin to see which variables are set with
mvn help:system
However the normal properties usage should work too. In the large context however I am wondering... what do you want to do? There might be a simpler solution.
The maven surefire plugin also has an option to set environment variables, just add this to your plugin configuration.
<environmentVariables>
<my_parameter1>value</my_parameter1>
</environmentVariables>
I think this requires that the plugin operates in fork mode, which is the default.

Categories

Resources