Convention for maven properties: "dot case" or "camel case"? - java

Using java and Maven, what is the convention for maven properties?
I am posting 2 examples here, both of which are in widespread usage. Which one is correct, according to convention?
Example A
<properties>
<hibernate.version>4.3.8.Final</hibernate.version>
<hsqldb.version>2.3.2</hsqldb.version>
<log4j2.version>2.0.2</log4j2.version>
</properties>
Example B
<properties>
<hibernateVersion>4.3.8.Final</hibernateVersion>
<hsqldbVersion>2.3.2</hsqldbVersion>
<log4j2Version>2.0.2</log4j2Version>
</properties>
Edit:
Here is a link to a Maven Properties Guide. Some examples of maven properties include ${project.build.directory} (dot case) and ${project.build.outputDirectory} (both dot case and camel case).
And the official documentation Maven POM Reference suggests an example property named <someVar> (camel case).

After reading the relevant documentation, the answer to this was clear all along.
The apparent conflict between dot.case and camelCase is that one is used to reference the hierarchical structure within the POM whilst the other is used for variable naming.
For example, let us look at ${project.build.outputDirectory}. The dot notation here, as far as I can understand, refers to the pom structure where the variable is located, whereas the variable name itself is indeed in camel case.
<project>
<build>
<outputDirectory>/opt/foo</outputDirectory>
</build>
</project>
In other words, the convention is as follows:
To refer to variables located elsewhere in the POM, combine path segments such as project or build with the . separator, i.e. use dot.case. Examples:
project.build.<variable>
maven.compiler.<variable>
To name the actual path segments, including the variable name itself (last segment), use lowerCamelCase. Examples:
outputDirectory (as in project.build.outputDirectory)
target (as in maven.compiler.target)
It is worth noting that most open source projects (including e.g. Spring Boot, pre-Gradle-migration - see here) use .version as a path segment and not as an addition to the variable name.
Consistency is the most important consideration. If your codebase is using someDependencyVersion, stick to that - else prefer someDependency.version.

I may be late to the party, but here's my 2 cents.
Consider you may want to check if there's a newer versions available. You have to find each dependency reference within the pom to know the library's groupId and artifactId.
On the other hand, if you use a naming convention shown below, you immediately know whether the version is a reference to a groupId or an artifactId and you can just copy-paste it and search for latest version.
<properties>
<ch.qos.logback.version>1.2.5</ch.qos.logback.version>
<logstash-logback-encoder.version>6.6</logstash-logback-encoder.version>
</properties>

Related

Is there a way to use jars with no-compliant name? [duplicate]

My project depends on Netty Epoll transport. Here is dependency:
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport-native-epoll</artifactId>
<version>${netty.version}</version>
<classifier>${epoll.os}</classifier>
</dependency>
The auto-generated module name for this dependency is:
netty.transport.native.epoll
And as the native keyword is reserved in Java 9 I can't add this module as a dependency to my project:
module core {
requires netty.transport.native.epoll;
}
Due to:
module not found: netty.transport.<error>
Additionally the jar tool --describe-module reports the following:
Unable to derive module descriptor for:
netty-transport-native-epoll-4.1.17.Final-SNAPSHOT-linux-x86‌_64.jar
netty.transport.native.epoll: Invalid module name: 'native' is not a
Java identifier
Are there any workarounds? (except "release correct netty artifact", of course).
EDIT:
As the quick fix for maintainers - you can add next line to build:
<manifestEntries>
<Automatic-Module-Name>netty.transport.epoll</Automatic-Module-Name>
</manifestEntries>
The solution to this seems to be:-
A way possible to uninterruptedly using the same artifact name with a new(different) module name could be by packaging META-INF/MANIFEST.MF of the artifact with an attribute Automatic-Module-Name which governs the name of the module to be used by the module descriptor when converted as an automatic module.
OR
Artifact owners can add module declarations using module-info.java to their JAR. (this could result in a slow bottom-up migration)
Since the module declaration defined in the specs as:
A module declaration introduces a module name that can be used in
other module declarations to express relationships between modules. A
module name consists of one or more Java identifiers (§3.8) separated
by "." tokens.
Intersetingly the declarations suggests -
In some cases, the Internet domain name may not be a valid package
name. Here are some suggested conventions for dealing with these
situations:
If the domain name contains a hyphen, or any other special character
not allowed in an identifier (§3.8), convert it into an underscore.
If any of the resulting package name components are keywords (§3.9),
append an underscore to them.
If any of the resulting package name components start with a digit, or
any other character that is not allowed as an initial character of an
identifier, have an underscore prefixed to the component.
But keep in mind as you do so that Underscore is a keyword in Java9
int _; // is would throw an error on javac based out of JDK9
int _native; // works fine
From now on you can also use this small Maven plugin to automatically modify the manifest file in a Scala jar in your local Maven repo: https://github.com/makingthematrix/scala-suffix
Under the link you will find the overview of the whole issue and what you need to add to you pom.xml, but I was asked to also explain here, so here it goes:
As it was mentioned already, Java does not recognize suffixes in modules names like _2.13 as version numbers and treat them as integral parts of modules names. So, when your project tries to use a class from the Scala dependency, it will look for your.scala.dependency.2.13 instead of just your.scala.dependency, it will fail to do it, and it will crash.
To fix this on your side (i.e. without any action from the library's creator) add this to the <plugins> section of your pom.xml:
<plugin>
<groupId>io.github.makingthematrix</groupId>
<artifactId>scala-suffix-maven-plugin</artifactId>
<version>0.1.0</version>
<configuration>
<libraries>
<param>your-scala-dependency</param>
</libraries>
</configuration>
<executions>
<execution>
<goals>
<goal>suffix</goal>
</goals>
</execution>
</executions>
</plugin>
where your-scala-dependency is a name of your Scala dependency without the version suffix (if there are more than one, just add them with more <param> tags). This should be the same as artifactId in your <dependency> section.
The plugin modifies the dependency's JAR file in your local Maven repository. It opens the jar, reads META-INF/MANIFEST.MF and adds to it a line:
Automatic-Module-Name: your-scala-dependency
If the property Automatic-Module-Name already exists, the plugin does nothing - we assume that in that case the dependency should already work. This prevents the plugin from modifying the same JAR file more than once.

Reading environment variable in the maven pom file [duplicate]

I am using maven as build tool. I have set an environment variable called env. How can I get access to this environment variable's value in the pom.xml file?
Check out the Maven Properties Guide...
As Seshagiri pointed out in the comments, ${env.VARIABLE_NAME} will do what you want.
I will add a word of warning and say that a pom.xml should completely describe your project so please use environment variables judiciously. If you make your builds dependent on your environment, they are harder to reproduce
It might be safer to directly pass environment variables to maven system properties. For example, say on Linux you want to access environment variable MY_VARIABLE. You can use a system property in your pom file.
<properties>
...
<!-- Default value for my.variable can be defined here -->
<my.variable>foo</my.variable>
...
</properties>
...
<!-- Use my.variable -->
... ${my.variable} ...
Set the property value on the maven command line:
mvn clean package -Dmy.variable=$MY_VARIABLE
Also, make sure that your environment variable is composed only by UPPER CASE LETTERS.... I don't know why (the documentation doesn't say nothing explicit about it, at least the link provided by #Andrew White), but if the variable is a lower case word (e.g. env.dummy), the variable always came empty or null...
i was struggling with this like an hour, until I decided to try an UPPER CASE VARIABLE, and problem solved.
OK Variables Examples:
DUMMY
DUMMY_ONE
JBOSS_SERVER_PATH
(NOTE: I was using maven v3.0.5)
I Hope that this can help someone....
Can't we use
<properties>
<my.variable>${env.MY_VARIABLE}</my.variable>
</properties>
I was struggling with the same thing, running a shell script that set variables, then wanting to use the variables in the shared-pom. The goal was to have environment variables replace strings in my project files using the com.google.code.maven-replacer-plugin.
Using ${env.foo} or ${env.FOO} didn't work for me. Maven just wasn't finding the variable. What worked was passing the variable in as a command-line parameter in Maven. Here's the setup:
Set the variable in the shell script. If you're launching Maven in a sub-script, make sure the variable is getting set, e.g. using source ./maven_script.sh to call it from the parent script.
In shared-pom, create a command-line param that grabs the environment variable:
<plugin>
...
<executions>
<executions>
...
<execution>
...
<configuration>
<param>${foo}</param> <!-- Note this is *not* ${env.foo} -->
</configuration>
In com.google.code.maven-replacer-plugin, make the replacement value ${foo}.
In my shell script that calls maven, add this to the command: -Dfoo=$foo
You can use <properties> tag to define a custom variable and ${variable} pattern to use it
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<!-- define -->
<properties>
<property.name>1.0</property.name>
</properties>
<!-- using -->
<version>${property.name}</version>
</project>

Require akka in module-info.java [duplicate]

My project depends on Netty Epoll transport. Here is dependency:
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport-native-epoll</artifactId>
<version>${netty.version}</version>
<classifier>${epoll.os}</classifier>
</dependency>
The auto-generated module name for this dependency is:
netty.transport.native.epoll
And as the native keyword is reserved in Java 9 I can't add this module as a dependency to my project:
module core {
requires netty.transport.native.epoll;
}
Due to:
module not found: netty.transport.<error>
Additionally the jar tool --describe-module reports the following:
Unable to derive module descriptor for:
netty-transport-native-epoll-4.1.17.Final-SNAPSHOT-linux-x86‌_64.jar
netty.transport.native.epoll: Invalid module name: 'native' is not a
Java identifier
Are there any workarounds? (except "release correct netty artifact", of course).
EDIT:
As the quick fix for maintainers - you can add next line to build:
<manifestEntries>
<Automatic-Module-Name>netty.transport.epoll</Automatic-Module-Name>
</manifestEntries>
The solution to this seems to be:-
A way possible to uninterruptedly using the same artifact name with a new(different) module name could be by packaging META-INF/MANIFEST.MF of the artifact with an attribute Automatic-Module-Name which governs the name of the module to be used by the module descriptor when converted as an automatic module.
OR
Artifact owners can add module declarations using module-info.java to their JAR. (this could result in a slow bottom-up migration)
Since the module declaration defined in the specs as:
A module declaration introduces a module name that can be used in
other module declarations to express relationships between modules. A
module name consists of one or more Java identifiers (§3.8) separated
by "." tokens.
Intersetingly the declarations suggests -
In some cases, the Internet domain name may not be a valid package
name. Here are some suggested conventions for dealing with these
situations:
If the domain name contains a hyphen, or any other special character
not allowed in an identifier (§3.8), convert it into an underscore.
If any of the resulting package name components are keywords (§3.9),
append an underscore to them.
If any of the resulting package name components start with a digit, or
any other character that is not allowed as an initial character of an
identifier, have an underscore prefixed to the component.
But keep in mind as you do so that Underscore is a keyword in Java9
int _; // is would throw an error on javac based out of JDK9
int _native; // works fine
From now on you can also use this small Maven plugin to automatically modify the manifest file in a Scala jar in your local Maven repo: https://github.com/makingthematrix/scala-suffix
Under the link you will find the overview of the whole issue and what you need to add to you pom.xml, but I was asked to also explain here, so here it goes:
As it was mentioned already, Java does not recognize suffixes in modules names like _2.13 as version numbers and treat them as integral parts of modules names. So, when your project tries to use a class from the Scala dependency, it will look for your.scala.dependency.2.13 instead of just your.scala.dependency, it will fail to do it, and it will crash.
To fix this on your side (i.e. without any action from the library's creator) add this to the <plugins> section of your pom.xml:
<plugin>
<groupId>io.github.makingthematrix</groupId>
<artifactId>scala-suffix-maven-plugin</artifactId>
<version>0.1.0</version>
<configuration>
<libraries>
<param>your-scala-dependency</param>
</libraries>
</configuration>
<executions>
<execution>
<goals>
<goal>suffix</goal>
</goals>
</execution>
</executions>
</plugin>
where your-scala-dependency is a name of your Scala dependency without the version suffix (if there are more than one, just add them with more <param> tags). This should be the same as artifactId in your <dependency> section.
The plugin modifies the dependency's JAR file in your local Maven repository. It opens the jar, reads META-INF/MANIFEST.MF and adds to it a line:
Automatic-Module-Name: your-scala-dependency
If the property Automatic-Module-Name already exists, the plugin does nothing - we assume that in that case the dependency should already work. This prevents the plugin from modifying the same JAR file more than once.

difference of artifactId and name in maven POM

I am new to maven and I'm confused about the difference between the artifactId and name.
What I know is that artifactId is the name of the artifact you are creating. I know that artifactId together with the groupId is use to uniquely identifies an artifact. So what is <name> purpose in POM. like the pom below I got from a site there is an artifactId and at the same time a <name>.
<groupId>org.sonatype.mavenbook.multi</groupId>
<artifactId>simple-parent</artifactId>
<packaging>pom</packaging>
<version>1.0</version>
<name>Multi Chapter Simple Parent Project</name>
You are correct that the artifactId helps identify the project.
The name is simply a human-readable "friendly" name. It is not required for a basic setup.
From the Maven documentation,
artifactId: The artifactId is generally the name that the project is known by. Although the groupId is important, people within the group will rarely mention the groupId in discussion ... It, along with the groupId, create a key that separates this project from every other project in the world (at least, it should :) ). Along with the groupId, the artifactId fully defines the artifact's living quarters within the repository.
The groupId, artifactId and version form a composite unique identifier (or coordinate) for this project. Each of these values has a fairly rigid naming convention that allows well organized groups, artifacts and versions.
The name is simply a readable name for the project and does not need to be unique or comply to the same conventions (so it can contain spaces and other characters).
The name is used for the project used by maven to build the artifact, while the artifact-id is used to identify the artifact that will be built.
For example:
This pom file definition for the rsts ear file:
Causes the rsts-ear project to be imported into Eclipse:
But creates the rsts_ear artifact in the nexus:
This means that the artifact-id, not the name, is referenced to include the artifact in the build as part of another artifact.

maven dependency version?

I am new to maven. i have a project and it has a pom. inside the pom there is a dependency as below:
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>some-project</artifactId>
<version>${originalVersion}</version>
<scope>compile</scope>
</dependency>
My question is where is ${originalVersion} value coming from?
Thanks!
It is either defined somewhere else in the pom, in a parent-pom (there can be several of those, because parents can have parents too), or via a profile (that might be defined somewhere else, like your settings.xml). It could also have been passed as a command-line parameter to maven, but you'd probably have noticed that.
originalVersion is not a standard Maven property so it must appear elsewhere such as in a parent pom, like this:
<properties>
<originalVersion>1.2</originalVersion>
</properties>
See Maven Properties Guide
It comes from a property in your pom.xml.
Something like that:
<properties>
<originalVersion>1.0</originalVersion>
</properties>
Look for a <properties> section in the pom.xml file, there must be a entry like <originalVersion>...</originalVersion>.
Check the properties sub section on the maven tutorial page. It says, following are the possible ways to reference a vairable
env.X: Prefixing a variable with "env." will return the shell's environment variable. For example, ${env.PATH} contains the $path
environment variable (%PATH% in Windows).
project.x: A dot (.) notated path in the POM will contain the corresponding element's value. For example:
1.0 is accessible via
${project.version}.
settings.x: A dot (.) notated path in the settings.xml will contain the corresponding element's value. For example:
false is accessible via
${settings.offline}.
Java System Properties: All properties accessible via java.lang.System.getProperties() are available as POM properties, such
as ${java.home}.
x: Set within a element or an external files, the value may be used as ${someVar}.

Categories

Resources