Require akka in module-info.java [duplicate] - java

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.

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.

Disabling Maven Dependency?

I'm having a strange problem with my project. There are two dependencies in my POM.xml that belong to my company's repository that I would like to delete and replace them with others that are in my local machine . However, when I do, the maven build fails with the following error:
Error:(21,27) java: unmappable character (0xE9) for encoding UTF-8
All I did was delete the two dependencing from POM and from classpath and replace them with the libraries in my local machine.
Could somebody please tell me why the build fails when I delete them from the POM, as if the encoding was depended on them?! And most importantly, if I can't delete them, is there a way I could keep in the POM all while disabling them?
I tried to edit the libraries themselves by addng:
<scope>system</scope>
<systemPath>Path/to/the/local/library</systemPath>
But Maven didn't like it:
'build.plugins.plugin.(groupId:artifactId)' must be unique but found duplicate declaration of plugin org.apache.maven.plugins:maven-jar-plugin # line 865, column 21
Reporting configuration should be done in <reporting> section, not in maven-site-plugin <configuration> as reportPlugins parameter. #

Maven un-ban a dependency (in order to use a library)?

We have a bill of material for all our projects that banned a certain dependency in the parent pom.xml. Now we need to use another library that uses that dependency. I can make an exclusion to exclude that banned dependency to compile. However, that makes the library throw a java.lang.NoClassDefFoundError. Given that we do not want to remove the ban in the parent pom, is there a way that I can bring it in for just the library?
Accordind to the documentation you could use includes for that:
includes - a list of artifacts to include. These are exceptions to the excludes. It is meant to allow wide exclusion rules with wildcards and fine tune using includes. If nothing has been excluded, then the includes have no effect. In otherwords, includes only subtract from artifacts that matched an exclude rule.
For example, to ban all xerces except xerces-api you would exclude "xerces" (groupId) and include "xerces:xerces-api"
You can skip execution of the enforcer plugin via the pom.xml in 2 ways:
Through a property:
<properties>
<enforcer.skip>true</enforcer.skip>
</properties>
Through plugin configuration
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>

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.

What are unused/undeclared dependencies in Maven? What to do with them?

Maven dependency:analyze complains about the dependencies in my project. How does it determine which are unused and which are undeclared? What should I do about them?
Example:
$ mvn dependency:analyze
...
[WARNING] Used undeclared dependencies found:
[WARNING] org.slf4j:slf4j-api:jar:1.5.0:provided
[WARNING] commons-logging:commons-logging:jar:1.1.1:compile
[WARNING] commons-dbutils:commons-dbutils:jar:1.1-osgi:provided
[WARNING] org.codehaus.jackson:jackson-core-asl:jar:1.6.1:compile
...
[WARNING] Unused declared dependencies found:
[WARNING] commons-cli:commons-cli:jar:1.0:compile
[WARNING] org.mortbay.jetty:servlet-api:jar:2.5-20081211:test
[WARNING] org.apache.httpcomponents:httpclient:jar:4.0-alpha4:compile
[WARNING] commons-collections:commons-collections:jar:3.2:provided
[WARNING] javax.mail:mail:jar:1.4:provided
Note:
A lot of these dependencies are used in my runtime container and I declared them as provided to avoid having the same library on the classpath twice with different versions.
Not sure how Maven determines this. It is not required to address all the items reported by this, but this information can be used as appropriate.
Used undeclared dependencies are those which are required, but have not been explicitly declared as dependencies in your project. They are however available thanks to transitive dependency of other dependencies in your project. It is a good idea to explicitly declare these dependencies. This also allows you to control the version of these dependencies (perhaps matching the version provided by your runtime).
As for unused declared dependencies, it is a good idea to remove them. Why add unnecessary dependency to your project? But then transitivity can bring these in anyway, perhaps, conflicting with your runtime versions. In this case, you will need to specify them — essentially to control the version.
By the way, mvn dependency:tree gives the dependency tree of the project, which gives you a better perspective of how each dependency fits in in your project.
The answer to:
"How does it determine which are unused and which are undeclared?".
Maven uses Object WebASM framework that analyzes your raw bytecode. It goes through all your classes and then builds a list of all classes that these reference. That is the how.
As to what to do, I would not recommend removing the "unused, declared dependecies" unless you are absolutely sure they actually unused.
Used undeclared dependencies
Simply, they are the transitive dependencies which you are using them but WITHOUT declaring them explicitly inside your POM file.
In the below digram, the orange colored one.
Hint:
It is good idea to declare them inside your POM file to be loosly coupled against your first level dependencies, so in the future if they planned to change their implementation and not to use this transitive dependency anymore, your application will be safe!
Unused declared dependencies
Simply, they are the dependencies which you are declearing them inside your POM file WITHOUT using them in your application code.
In the below digram, the red colored one.
Hint:
It is good idea to remove them from your POM file, because they are not used and to save the final size of the application artifact also to avoid any developer from using wrong classes by mistake!
This can be easily fixed with by adding ignoredUnusedDeclaredDependencies in pom.xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<configuration>
<ignoredUnusedDeclaredDependencies>
<ignoredUnusedDeclaredDependency>org.slf4j:slf4j-api</ignoredUnusedDeclaredDependency>
</ignoredUnusedDeclaredDependencies>
</configuration>
</execution>
</executions>
</plugin>

Categories

Resources