How to export all packages from Java 9 module? [duplicate] - java

This question already has an answer here:
Why is exporting the entire module not allowed?
(1 answer)
Closed 5 years ago.
Right now, for every module I have, I need to explicitly specify packages I want to export. For example:
module core {
exports cc.blynk.server.core;
exports cc.blynk.server.core.protocol.handlers.decoders;
exports cc.blynk.server.core.protocol.handlers.encoders;
}
However, it is not very convenient. I would like to do something like that:
module core {
exports cc.blynk.server.core.*;
}
Is there any way to do that? Where this limitation comes from?

No, you can not use a wildcard to export all packages within the module. You will have to export each package explicitly.
It is not allowed since this could majorly lead to conflicts in the different packages exported from different modules which defies the purpose of modularising the code.
Additionally quoting from one of the threads:
The packages exported by a module are meant to be a stable API that
consumers can rely on. For this reason, we make the module author
spell out the exported packages explicitly. This also dials down the
likelihood of multiple modules needlessly exporting the same package.
Additionally, it avoids the confusion that would occur if com.abs.*
was exported without qualification while com.abs.foo was exported with
qualification.

Related

How do I generate JavaDocs for non-exported packages in a module?

I am currently writing a JavaFX application contained within 1 module and I want to use Javadoc to document all of my code. However, I am noticing that I can't seem to generate Javadocs for packages that have not been exported out of the module in module-info.java. On one hand, that makes sense. Non-exported packages aren't part of the public API. On the other hand, I feel like surely there should be options to enable documentation of internal APIs hidden in non-exported packages, but I've had no success in enabling them.
As this is a Maven project, I've tried the following options with the maven-javadoc-plugin:
<show>private</show>
<additionalOptions>-private</additionalOptions>
<additionalOptions>--show-module-contents all --show-packages all --show-types private</additionalOptions>
None of these work (and I am pretty sure 1 and 2 are the exact same thing). They only show a bit more info on one package that i've exported to another specific module. If I don't have these options, the Modules section of the Javadoc is completely blank with the exception of the module name.
I've done lots of Googling and no one on the Internet seems to bring this issue up. Maybe my Google-Fu is just off? I feel like there's just some silly undocumented flag that I haven't found yet because it can't be the case that you have to export the packages to get Javadocs for them, right?
My project consists of only one module containing 8 packages. None of them need to be fully exported out yet. Only one package containing my JavaFX files needs to be exported to javafx.graphics and that's the only one that gets picked up by Javadoc when I enable <show>private</show>.
Here is a gist of my module and Maven config, if anybody needs it:
https://gist.github.com/urbenlegend/753de7bec598fd07d6b5c0b0ef02d1d0
I am invoking Javadoc generation via mvn compile javadoc:javadoc
Anyone here have any tips? Thanks in advance!

How to modify the AST using Java 9+ [duplicate]

This question already has answers here:
Accessing com.sun.tools.javac.util from Java 9
(2 answers)
Closed 3 years ago.
I've been trying to modify the AST using annotation processors. I tried extending Lombok, but that seemed too hard, so I decided to use things from com.sun.source.* and com.sun.tools.javac.* However, I am using java 11, and the document I was learning from, "The Hacker's Guide to Javac" http://scg.unibe.ch/archive/projects/Erni08b.pdf, uses Java 6. The api they used is now internal and my module cannot read it.
In IntelliJ, it gave me a few errors, but I clicked on the suggestions (which said things like "Add --Xxx-xxx to xxx" without paying attention to them. When I tried compiling with Maven, it failed, since the module does not read the internals of jdk.compiler.
These are some of my imports:
import com.sun.source.util.Trees;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.TreeMaker;
import com.sun.tools.javac.tree.TreeTranslator;
import com.sun.tools.javac.util.Context;
My module-info file contains
requires jdk.compiler;
requires java.compiler;
I got messages like "[ERROR]package com.sun.tools.javac.util is declared in module jdk.compiler, which does not export it to module OtherAnnot" and "[ERROR] (package com.sun.tools.javac.tree is declared in module jdk.compiler, which does not export it to module OtherAnnot)"
Edit: I guess this is a duplicate, but I wanted to know if there was some alternative API for AST transformations in java 9.
With the introduction of Project Jigsaw, the JDK has been modularized, allowing users to create their own modules as well. These modules allows you to export packages of yours, allowing programs that require your module (in their module-info.java) to use the exported packages.
Ideally, you'd be prohibited from using classes that reside in packages that are not exported. However, to not break backwards compatibility, VM flags were introduced that allow you to forcefully export packages (that don't belong to you) to your module.
Given your error message, the respective VM flag to add is:
--add-exports jdk.compiler/com.sun.tools.javac.tree=OtherAnnot
The pattern here is:
--add-exports THEIR_MODULE/THEIR_PACKAGE=YOUR_MODULE
If the compiler complains that packages aren't exported to the unnamed module, then you can use the following:
--add-exports THEIR_MODULE/THEIR_PACKAGE=ALL-UNNAMED

How to get Eclipse to stop asking to create a module-info java file on new Java project creation?

Everytime I try to create a new java project Eclipse keeps asking if I want to add a module-info java file to the source folder. It's getting pretty annoying as there's no immediately obvious option to opt out of this check.
IDE for Java Developers, Photon release 4.8.0
See while creating a new project, after you click>> next on the very first dialog "new java project." There is one another dialog box pops up when you click >> finish. It will lead you to the 3rd dialog box which asks for the creation of module-info java file?? & gives you two option create & don't create.
You should select "don't create."
Here are some advantages of the file
module-info.java contents:
To declare a jar file as a named module, one needs to provide a module-info.class file, which is, naturally, compiled from a module-info.java file. It declares the dependencies within the module system and allows the compiler and the runtime to police the boundaries/access violations between the modules in your application. Let’s look at the file syntax and the keywords you can use.
Module module.name – declares a module called module.name.
Requires module.name – specifies that our module depends on the module module.name, allows this module to access public types exported in the target module.
Requires transitive module.name – any modules that depend on this module automatically depend on module.name.
Exports pkg.name says that our module exports public members in package pkg.name for every module requiring this one.
Exports pkg.name to module.name the same as above, but limits which modules can use the public members from the package pkg.name.
Uses class.name makes the current module a consumer for service class.name.
Provides class.name with class.name.impl registers class.name.impl class a service that provides an implementation of the class.name service.
opens pkg.name allows other modules to use reflection to access the private members of package pkg.name.
Opens pkg.name to module.name does the same, but limits which modules can have reflection access to the private members in the pkg.name.
One great thing about the module-info.java syntax is that the modern IDEs would fully support your efforts of writing them. Perhaps all of them would work beautifully. I know that IntelliJ IDEA does content assist, quick fixes of the module files when you import classes from the module you haven’t required yet, and so on. I don’t doubt Eclipse IDE and NetBeans IDE offer the same.
Perhaps this is not a perfect solution, but it will stop asking if you choose to use Java version 8 compiler (JavaSE-1.8). If you need any newer Java version, I'm affraid don't have an answer.

How split packages are avoided in Java 9

I am new to Java 9 and was going though the modular video lectures by Java on YouTube.
They mentioned 3 benefits of modularization-
1. No missing dependencies
2. No cyclic dependnpcies
3. No split packages.
As far as I understand about split packages is that let's say an application is dependant on multiple dependncies and let's say package abc.pqr.xyz is present in more that 1 jar.
Then there is a chance that some of the classes in that package will be used from jar1 while other classes from jar2.
This might lead to some problems at runtime which will be hard to debug.
Video says modularization solves this issue.
But how that's what I am trying to understand?
Let's say there is test.module1 which has below module info -
module test.module1{
exports abc.pqr.xyz;
}
Another module2 with below module info-
module test.module2{
exports abc.pqr.xyz;
}
Now let's say in my application I added dependencies of both of these modules-
module test.myapp{
requires test.module1;
requires test.module2;
}
Now again I have 2 modular dependencies where there is a chance that some of the classes will be present in both of these modules.
So at runtime how it will be resolved from which module to pick up the class definitions?
How Java 9 will avoid split packages problem?
With the scenario described in the question, you'll start facing an error reading :
Module test.myapp reads package from both test.module1 and test.module2
Readability of the Modules from The State of the Module System elaborates over the use of Modules as follows and shall interest your use-case(emphasis mine):
The readability relationships defined in a module graph are the basis
of reliable configuration: The module system ensures
that every dependence is fulfilled by precisely one other module
that the module graph is acyclic
that every module reads at most one module defining a given package
and that modules defining identically-named packages do not interfere with each other.
the benefit of implying the same in the module system is detailed as well
Reliable configuration is not just more reliable; it can also be
faster. When code in a module refers to a type in a package then that
package is guaranteed to be defined either in that module or in
precisely one of the modules read by that module.
When looking for the
definition of a specific type there is, therefore, no need to search
for it in multiple modules or, worse, along the entire class path.
That said, the current solution to your implementation is
if the modules test.module1 and test.module2 are explicit modules, you can choose to implement the package abc.pqr.xyz in either one of them
OR you pull it out from both into a separate module test.mergeModule of your own which can thereafter be used as an independent module across its clients.
if these(or any one of them) are automatic modules, you can make use of the bridge extended to the classpath and let such jar remain on the classpath and be treated as the unnamed module, which shall by default export all of its packages. At the same time, any automatic module while reading every other named module is also made to read the unnamed module.
Quoting the document again and to illustrate with an example, so that you can correlate to your question :
If code in the explicit module com.foo.app refers to a public type in
com.foo.bar, e.g., and the signature of that type refers to a type in
one of the JAR files still on the class path, then the code in
com.foo.app will not be able to access that type since com.foo.app
cannot depend upon the unnamed module.
This can be remedied by treating com.foo.app as an automatic module temporarily, so that its
code can access types from the class path, until such time as the
relevant JAR file on the class path can be treated as an automatic
module or converted into an explicit module.
The Java module system resolves the split package problem by rejecting this sort of scenario at JVM startup time. When the JVM starts it will immediately begin resolving the module graph, and when it encounters two modules in test.myapp's module path, the JVM will throw an error indicating test.module1 and test.module2 are attempting to export the same package.

Where has sun.misc.Perf moved now that tools.jar was decomposed in Java 9

sun.misc.Perf was in tools.jar and in Java 9 this was removed and restructured based on the modules concept, so the question is how do you access it in newer Java?
I need to know which module now contains this code.
The implementation has been moved under the jdk.internal.perf package within the java.base module.
As the name already suggests, the package has not been exported from the module and hence if you still want to explicitly make use of the classes within this package, you can make use of the VM option:
--add-exports java.base/jdk.internal.perf=<your-module-name>
Do note though, this is an unreliable way of making use of such classes and a better solution would always be to migrate for the specific use cases without depending on the (internal) sun.misc.* classes.

Categories