Override property key's value in maven - java

I have global property file (global.properties) with below mentioned content
app.server.username=globalUser
I have another property file called sample.properties with below mentioned content
app.server.username=sampleUser
app.server.port=443
Now, I need to replace app.server.username key value from "sampleUser" to "globalUser" using Maven , with packaging of jar file happens.
These 2 properties file is placed in same folder within Java project.
So, during Maven build phase (or in package phase) , Maven should refer to global.properties, search for all key value pairs (defined in it) in sample.properties. And replace value of all matched keys.
So , after Maven build, sample.properties files should have below mentioned content
app.server.username=globalUser
app.server.port=443
Please suggest how to do it in Maven ?

You can use the properties plugin for that, specifying multiple files to be read:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-maven-plugin</artifactId>
<version>1.0.0</version>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>read-project-properties</goal>
</goals>
<configuration>
<files>
<file>global.properties</file>
<file>sample.properties</file>
</files>
</configuration>
</execution>
</executions>
</plugin>
From my test results, the latter files will cause duplicate property keys to override the former ones. So just ensure that your files are listed in the correct order.

Related

How to specify separately the path of the java file and the tokens file generated by Antlr?

I`m attempting to use antlr4 in my project to parse files in custom format. But when I use antlr4 maven plugin, I cannot find a parameter to set separately the path of tokens file and java file, as it can only set a common path.
Here`s the configuration of antlr4 maven plugin:
<plugin>
<groupId>org.antlr</groupId>
<artifactId>antlr4-maven-plugin</artifactId>
<version>4.11.1</version>
<executions>
<execution>
<id>antlr</id>
<goals>
<goal>antlr4</goal>
</goals>
<phase>compile</phase>
</execution>
</executions>
<configuration>
<libDirectory>src/main/antlr4/imports</libDirectory>
<sourceDirectory>src/main/antlr4</sourceDirectory>
<outputDirectory>src/main/java</outputDirectory>
<listener>true</listener>
<visitor>true</visitor>
<treatWarningsAsErrors>true</treatWarningsAsErrors>
</configuration>
</plugin>
The grammar file test.g4 is in <sourceDirectory>/relativePath(src/main/antlr4/org/trance233/antlr/).
The .tokens file is in <outputDirectory>(src/main/java/), the .java file is in <sourceDirectory>/relativePath(src/main/java/org/trance233/antlr/).
Is there any way that can set the path separately? Such as the .tokens file above is put in src/main/resources, and the .java file is put in src/main/java/org/trance233/antlr/.
A configuration for antlr4 is usually very simple like this:
<plugin>
<groupId>org.antlr</groupId>
<artifactId>antlr4-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>antlr4</goal>
</goals>
<configuration>
<visitor>true</visitor>
<listener>false</listener>
</configuration>
</execution>
</executions>
</plugin>
This assumes you have your grammar file in src/main/antlr4/<package>/test.g4 (default location). There is no need to configure such things etc. because by conventions the generated class will be available in target/generated-sources/antlr4/. Exactly in this directory you will find the *.tokens files. The imports directory is defined by default as src/main/antl4/imports. The default configuration for the antlr4-maven-plugin defines some very useful defaults and it is strongly recommended to follow those conventions.
I strongly recommmend NOT to configure the <outputDirectory>src/main/java</outputDirectory> because that will generate code in your src/ directory tree which can cause issues with your versions control system.
BTW: Binding the code generation to the phase compile is very bad because the code generation should be done before the compile phase. The generate-sources phase is exactly intended for such cases. This phase is used by default by the antlr4-maven-plugin.
Is there any way that can set the path separately?
No.
But you can remove the .tokens file: it is not needed at runtime for your generated parser classes.

Generated Sources Root gone after every git pull in IntelliJ

One of the many modules I'm working on uses "generated-sources" for a couple auto-generated Java classes that the rest of the code depends on. Unfortunately, every single time I do a git pull it gets reset and I have to do mark the folder as "Generated Sources Root" again.
It's not a deal breaker, but it's really annoying. Isn't there a way to automate this? I don't know, some setting in IntelliJ or perhaps even directly in the pom.xml?
You can give a try to build-helper-maven-plugin and add more source directories to your project explicitly:
<project>
...
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${project.build.directory}/generated-sources/...</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Also there is a little trick - actual source generation must happens before this goal execution.
In our project IDEA works pretty well with this approach.
Try adding generated-sources folder to git ignore file. Git ignore file if not already exists can be added in intelli idea like:
Then add generated-sources folder relative path like generated-sources/in git ignore file & commit .gitignore file. From next time any changes in that folder will not be overwritten or will be committed to server.

How to get same properties from different parent modules in maven?

I have a maven project with this structure.
I want to use same jar in different EARs with different properties.
When I run "mvn install", it creates 2 EARs but it cannot do filtering with this config. How can I solve this issue?
With Maven, you cannot filter a file belonging to a JAR module which is already built.
Each module is built and packaged separately. So, if you JAR needs to have a property which the value is populated dynamically, I may propose you two solutions :
Put the properties file which contains the key-value for conf.path in each EARs and in the JAR side, you could use a helper class to lookup in the classpath the value associated to the conf.path key.
You can perform this processing when the value is required or as soon as the application has started up if you need it very soon.
Create two flavors of your JAR whose the property differs. In this case, the property information is not stored any longer in the EAR but directly in the JAR
Look at the classifier element :
The classifier allows to distinguish artifacts that were built from
the same POM but differ in their content. It is some optional and
arbitrary string that - if present - is appended to the artifact name
just after the version number. As a motivation for this element,
consider for example a project that offers an artifact targeting JRE
1.5 but at the same time also an artifact that still supports JRE 1.4. The first artifact could be equipped with the classifier jdk15 and the
second one with jdk14 such that clients can choose which one to use.
Another common use case for classifiers is the need to attach
secondary artifacts to the project's main artifact. If you browse the
Maven central repository, you will notice that the classifiers sources
and javadoc are used to deploy the project source code and API docs
along with the packaged class files.
To produce multiple jars, configure the maven-jar-plugin plugin in your build in this way :
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<classifier>jarVersion2</classifier>
<includes>
<include>**/jarVersion2.properties</include>
</includes>
</configuration>
</execution>
<execution>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<classifier>jarVersion1</classifier>
<includes>
<include>**/jarVersion1.properties</include>
</includes>
</configuration>
</execution>
</executions>
</plugin>
After you can reference in your WAR the jarVersion artifact like that for the war 1:
<dependency>
<groupId>groupIdOfTheJar</groupId>
<artifactId>artifactIdOfTheJar</artifactId>
<version>versionOfTheJar</version>
<classifier>jarVersion1</classifier>
</dependency>
And like that for the war 2 :
<dependency>
<groupId>groupIdOfTheJar</groupId>
<artifactId>artifactIdOfTheJar</artifactId>
<version>versionOfTheJar</version>
<classifier>jarVersion2</classifier>
</dependency>

Use Maven Replace Plugin to replace a phrase on a generated Java file inside Target/generated-sources

I spent hours on this problem, searching several Google and SO entries, I have some ideas but not getting the result.
I have a maven file that does something like this:
grab a jar containing JSON schemas, and unpack them.
Using the Maven Replacer plugin (v 1.5.3), replace a line in a schema file called “MySchema.json” as such:
”Hello” :
”HelloWorld” :
then Maven would use another plugin to compile a class called “converter.java” and runs this class to output a Java file based on “MySchema.json”. let’s call the generated Java file “MyPojo.java”.
Now, I want Maven to replace a line in “MyPojo.java”, but no matter what I do I cannot achieve this.
I tried:
include a separate replace plugin entry for step 4 after the plugin that converts schemas to Java, but ofcourse this caused Maven to complain about existing replace plugin with same artifact/group id from step 2.
Tried adding a separate execution id to the goal “replace” for second plugin, this is invalid for this plugin.
There is a parent project to my current project folder, I tried putting another replacer plugin in the parent POM and make the phase to be any of the “package”, “generate-resources”, “compile”, etc. did not work. Note: the phase for replacements inside “MySchema.json” (in my current project POM) is generate-sources.
give absolute path to the Java, it kept complaining that path does not exist. But I copied and pasted the path to the Java inside windows explorer address bar after it was generated and could read it from Windows explorer. Note that the generated Java file “MyPojo.java”, went under “target/generated-sources” which is sourced by a parent POM above this project using a Maven Helper plugin in parent POM, so this folder should be visible as a source for further compilation. That Maven Helper plugin has phase generate-sources.
Use with same result as above
In my current project (non-parent one) this is the POM code:
<build>
<!—execute a plugin grab schemas jar and unpack schemas-->
...
<plugin>
<groupId>com.google.code.maven-replacer-plugin</groupId>
<artifactId>replacer</artifactId>
<version>1.5.3</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>replace</goal>
</goals>
</execution>
</executions>
<configuration>
<includes>
<include>${project.basedir}/target/schemas/MySchema.json</include>
</includes>
<replacements>
<replacement>
<token>"Hello":</token>
<value>"Hello World":</value>
</replacement>
</replacements>
</configuration>
</plugin>
<!-- execute a Plugin for converting shcemas to POJO -->
. . .
</plugins>
</build>
</project>
You should be able to declare the plugin only once and run two replace execution at different Maven Build Lifecycle phases:
Before the Json -> POJO conversion
After the Json -> POJO conversion
So, translating that into could would result in something like:
<plugin>
<!-- (unique) plugin declaration -->
<groupId>com.google.code.maven-replacer-plugin</groupId>
<artifactId>maven-replacer-plugin</artifactId>
<version>1.3.5</version>
<executions>
<!-- first execution: replace on json file -->
<execution>
<id>replace-for-json</id>
<phase>some-phase-before-conversion</phase>
<goals>
<goal>replace</goal>
</goals>
<configuration>
<filesToInclude>${project.basedir}/target/schemas/MySchema.json</filesToInclude>
<preserveDir>true</preserveDir>
<outputDir>target</outputDir>
<replacements>
<replacement>
<token>"Hello":</token>
<value>"Hello World (Json)":</value>
</replacement>
</replacements>
</configuration>
</execution>
<!-- second execution: replace on java file -->
<execution>
<id>replace-for-pojo</id>
<phase>some-phase-after-conversion</phase>
<goals>
<goal>replace</goal>
</goals>
<configuration>
<filesToInclude>${project.basedir}/target/generated-sources/MyPojo.java</filesToInclude>
<preserveDir>true</preserveDir>
<outputDir>target</outputDir>
<replacements>
<replacement>
<token>"Hello":</token>
<value>"Hello World (Java)":</value>
</replacement>
</replacements>
</configuration>
</execution>
</executions>
</plugin>
Source: Configuration for the maven-replacer-plugin on two separate executions

How to pass parameter to Maven plugin from CLI?

<build>
<plugins>
<plugin>
<groupId>org.jvnet.jax-ws-commons</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>wsimport</goal>
</goals>
<id>generate-sei</id>
<configuration>
<sourceDestDir>${project.basedir}/src/main/java</sourceDestDir>
</configuration>
</execution>
</executions>
<dependencies>...</dependencies>
</plugin>
</plugins>
</build>
The above XML snippet is from a POM file in a Java project. In this snippet I've defined the jaxws-maven-plugin to use a wsdl file to generate the SEI code and place it in the src/main/java directory. This plugin is bound to the generate-sources phase, and works fine.
I want to make it so that if I issue the plugin directly, using:
mvn jaxws:wsimport
it should place the files in the above mentioned folder. From the plugins reference site (https://jax-ws-commons.java.net/jaxws-maven-plugin/wsimport-mojo.html), I can't figure out how to pass the parameter (sourceDestDir) as a command line argument. Is there someway I can do this?
WARNING /!\
You are trying to generate sources under the source folder src/main/java. Unless there is a very strong reason, don't do this. All generated content should always be placed under the build directory (target by default) and not be version-controlled. You can always add the generated sources as source folder using the build-helper-maven-plugin:add-source, if the plugin does not do it already itself.
To be able to set parameters directly on the command line, the plugin needs to define a user property. However, the org.jvnet.jax-ws-commons:jaxws-maven-plugin does not define a user property for the sourceDestDir parameter. This is noticeable because the documentation does not have a "User Property" set.
You can also find this in the source code:
#Parameter(defaultValue = "${project.build.directory}/generated-sources/wsimport")
private File sourceDestDir;
The #Parameter annotation, used to declare the parameter of the Maven plugin, does not have a corresponding property.
As such, you will need to have the following:
Define a Maven property jaxws.sourceDestDir with a value of ${project.basedir}/src/main/java with
<properties>
<jaxws.sourceDestDir>${project.basedir}/src/main/java</jaxws.sourceDestDir>
</properties>
Preferably, you would have ${project.build.directory}/some/path instead of src/main/java.
Configure the plugin to use this Maven property:
<configuration>
<sourceDestDir>${jaxws.sourceDestDir}</sourceDestDir>
</configuration>
If you want to override it, you can now do so directly on the command line with -Djaxws.sourceDestDir=/my/new/value. This system property will take precedence over the value of the Maven property.

Categories