Compile non-modular code that depends on modules - java

I have a folder with two compiled modules simple-modules/module1 and simple-modules/module2 these contained exploded code, so not its jar and both modules contain a module-info.java
I have other non-modular source code in folder normal-java-packages that uses the API exposed by the mentioned modules.
So, as a first step I would like to compile that.
Reading: https://openjdk.org/projects/jigsaw/spec/sotms/#module-artifacts
As far as I understand, the code in normal-java-packages should be part of the classpath, so it will be included in the unnamedmodule, and it will able to access all JRE modules as well as my user-defined modules simple-modules/module1 and simple-modules/module2.
I am trying to run:
javac -p simple-modules -d output -cp normal-java-packages
However, it looks like something is off as I get:
error: no source files
Any suggestions or pointers on what may be the issue here?
EDIT:
Also tried this command as suggested:
javac -p simple-modules -d output classpath_entry/com/myuser/modules/main/MainApp.java
Getting these errors:
classpath_entry/com/myuser/modules/main/MainApp.java:3: error: package com.myuser.hello is not visible
import com.myuser.hello.HelloModules;
^
(package com.myuser.hello is declared in module hellomodule, which is not in the module graph)
classpath_entry/com/myuser/modules/main/MainApp.java:4: error: package com.myuser.greetings is not visible
import com.myuser.greetings.EnglishGreeting;
^
(package com.myuser.greetings is declared in module hellomodule, which is not in the module graph)
classpath_entry/com/myuser/modules/main/MainApp.java:5: error: package com.myuser.other is not visible
import com.myuser.other.Other;
^
(package com.myuser.other is declared in module greetings, which is not in the module graph)
3 errors
So it looks like the compiled exploded modules in simple-modules are not visible, any idea why ?

Ok, so I will answer my own question as I found out what the issue is:
the command to use is:
javac -p simple-modules -d output --add-modules ALL-MODULE-PATH classpath_entry/com/myuser/modules/main/MainApp.java
I still find a bit redundant the --add-modules ALL-MODULE-PATH
The JRE modules are loaded fine without it, I don't see why we need it even when we are already specifying the user defined modules in the module path -p already.

Related

Can an annotation processor make a new java module?

I am working on a tool for building modular projects, and one potential api for declaring external dependencies is for users to declare them directly on their module-info.java(s)
#Dependency(group="org.apache.commons", artifact="commons-lang3", version="3.12.0")
module jproject {
requires java.base;
requires jproject.annotations;
// Should come from the dependency above...somehow
requires org.apache.commons.lang3;
}
Bootstrap problem of getting jproject.annotations on the module-path aside, I suspect but have not yet confirmed that I could do the dependency resolution work here with an annotation processor.
javac --module-source-path modules/
--module jproject
--processor-path download_deps.jar
-proc:only
-d target/modules/
javac --module-source-path modules/
--module jproject
--processor-path ...
-d target/modules/
What I can't figure is if its even conceptually possible to merge these two steps - calling javac and having a processor download the relevant files too a common place.
Looking at the Filer class available to processors I see createResource which feels like the right direction to dump downloaded jars that way, but I don't understand the compilation process enough to know if the filer's output would go on the module-path and if not if there is any way to do this.

module-info not compiled unless package classes are compiled with the same command

I've got a folder called myModule. Inside it, there's another folder called myPackage in which my Main.class exists.
Next to myPackage I have my module-info.java which I'd like to compile. First take a look at the folders hierarchy:
-- myModule
-- myPackage
-- Main.class
-- module-info.java
The problem is when I want to compile my module-info.java with the following command:
javac module-info.java
I get the following error:
package is empty or does not exist: myPackage
But, when I put Main.java inside myPackage and then compile both files with the same command:
javac module-info.java myPackage/Main.java
the error disappears. I can't understand why this should happen?
TL;DR — A module-info.java file is not designed to be a stand-alone thing. It is designed to be part of a multi-source file compilation unit. A unit which includes the module descriptor, plus at least one other source file.
The long-winded version
„…there's another folder called myPackage in which my Main.class exists…“
I'm gonna assume you meant to type Main.java and that Main.class is an oversight since…
You don't mention anything about it being an already-compiled byte code file.
I can't think of a reason why anybody would intentionally put a .class file in a source directory.
I'm also gonna assume — although you didn't mention it at all in your question — that you're intentionally following the convention recommended in the Project Jigsaw: Module System Quick-Start Guide…
„…By convention, the source code for the module is in a directory that is the name of the module…“
I've established that compilation would succeed if your myModule module is just an empty module{} block. That is, if it doesn't declare that it exports myPackage. So I'm gonna also assume your module-info.java, like my experimental one, contains…
module myModule {
exports myPackage;
}
Keep in mind what the javac tool is designed to do…
Description
The javac command reads source files that contain module, package and type declarations written in the Java programming language…
Also consider the reliable configuration goal of the JPMS…
Reliable configuration, to replace the brittle, error-prone class-path mechanism with a means for program components to declare explicit dependences upon one another
If I sign a contract to mow your lawn every Saturday but then never turn up, how reliable am I? Imagine if it were legal for javac to compile a module-info.java file for a module that claimed to export a package, but that package had no classes in it. How reliable is such a module?
If my build downloaded your hypothetical myModule artifact from Maven Central, I could have an import myPackage.* in my class only to find there's nothing in it. What use is a package with nothing in it?
„The problem is when I want to compile my module-info.java with the following command:“
javac module-info.java
The clue to the mystery is the fact that the above command results in the same error when the myPackage directory contains legal source code.
The error message isn't telling you that the file system directory is empty. It's telling you that the package that you claim the module exports is empty. Empty as in: The compiler doesn't know anything about source code you never pass to it as part of a compilation unit.
„…the error disappears. I can't understand why this should happen?…“
By executing: javac module-info.java myPackage/Main.java, you're composing a compilation unit made up of the things the module declares it exports. Which is the way the JPMS documentation specifies the system is expected to be used…
$ javac -d mods/com.greetings \
src/com.greetings/module-info.java \
src/com.greetings/com/greetings/Main.java
So typos notwithstanding, the cause of the error you report is pretty simple: Compiling a module that doesn't contain any source files is not only pointless, as far as the compiler is concerned it is a malformed module. Therefore, it's illegal.

Compilation with javac fails, with eclipse-compiler it works

I'm trying to write a simple ant build to compile a project.
The project is in eclipse and there it compiles successfully (with the eclipse-compiler).
But with ant (using javac) it appears an error and i don't know how to resolve it.
Structure of the used jar:
com
xxx
a <= package
b
a.class
Codeblock of my class:
Object o = com.xxx.a.b.method();
^
The exception of ant is:
error: cannot find symbol
symbol: variable b
location: class a
I think eclipse uses the package first to try to compile the code. javac seems to think that a is the class.
Is there a way to resolve the problem without changing the jar?
It looks like either package name is different or you have multiple class files of the same name. I would suggest checking the import statements and adding the specific jar file to classpath while compiling using javac or ant command.
To find the exact jar file, use ctrl+T then paste your class name in the box and it will tell you the jar file. Add that jar file to your ant classpath and build.
I didn't find anything in the Java Language Specification that this is an error, so it might be a javac bug.
Since it is a javac vs. Eclipse compiler thing, try one of the following:
Use the Eclipse compiler in the Ant script
If it is a javac bug, the bug may be fixed in a newer (update) JDK version
If your code does not directly reference class com.xxx.a, compile the code with the JAR in which the class com.xxx.a was removed

"package javax.xml.soap is declared in module java.xml.ws, which is not in the module graph"

So I took the SOAP example at Working Soap client example , put it into a file SOAPClientSAAJ.java, and tried compiling it (Openjdk 9 on Debian):
t#h ~/javatest> javac SOAPClientSAAJ.java
SOAPClientSAAJ.java:1: error: package javax.xml.soap is not visible
import javax.xml.soap.*;
^
(package javax.xml.soap is declared in module java.xml.ws, which is not in the module graph)
1 error
After Googling some, I found out that compiling and running as
t#h ~/javatest> javac --add-modules java.xml.ws SOAPClientSAAJ.java
t#h ~/javatest> java --add-modules java.xml.ws SOAPClientSAAJ
works. See also this video for general background: https://www.youtube.com/watch?v=y8bpKYDrF5I&t=20m17s
Now, questions:
Shouldn't the compiler automatically add the module java.xml.ws ? (since it obviously knows it is needed) Is this a bug in javax.xml.soap ?
Why is the --add-modules option not documented in my man pages? (openjdk 9 in Debian)
What should I write in the .java file to automatically add the java.xml.ws module?
This is a result of the new Java 9 modules. The javax.xml.soap package is actually a Java EE package, and so now isn't visible. The current workaround is to either use the --add-modules, as you've done, or to modularize your code.
Modularizing your code requires restructuring it into modules, and including a module-info.java file that specifies the modules you're using. In your case, specifying java.se.ee would give access to all the EE modules.

JUnit - Java project structure

I have the following directory structure:
project/hamcrest-core-1.3.jar
project/junit-4.12.jar
project/build/
project/ija/ija2016/HomeWork2Test.java
project/ija/ija2016/homework2/model/cards/Card.java
project/ija/ija2016/homework2/model/cards/CardDeck.java
project/ija/ija2016/homework2/model/cards/CardStack.java
project/ija/ija2016/homework2/model/board/AbstractFactorySolitaire.java
project/ija/ija2016/homework2/model/cards/FactoryKlondike.java
The HomeWork2Test.java was given to us (I cannot edit this one) and contains tests for the other classes. In the header it has these imports:
package ija.ija2016.homework2;
import ija.ija2016.homework2.model.board.AbstractFactorySolitaire;
import ija.ija2016.homework2.model.board.FactoryKlondike;
import ija.ija2016.homework2.model.cards.Card;
import ija.ija2016.homework2.model.cards.CardDeck;
import ija.ija2016.homework2.model.cards.CardStack;
So I made the Card, CardStack and CardDeck classes into a package by specifying:
package ija.ija2016.homework2.model.cards;
in each of the files.
And the AbstractFactorySolitaire and FactoryKlondike have:
package ija.ija2016.homework2.model.board;
Now we are supposed to run the tests in the HomeWork2Test.java class using JUnit. However, when I try to run the following command from the project folder:
javac -cp junit-4.12.jar -d build ija/ija2016/homework2/HomeWork2Test.java
I get errors telling me that the:
package.ija2016.homework2.model.cards does not exist
package.ija2016.homework2.model.board does not exist
I don't exactly understand how to fix the project structure. Also how do I run the JUnit test?
Thank you for replies.
Well I think you are mixing concepts (compiling and running junit tests)
1st you need to compile your Classes (let's compile them to build
dir):javac -d build ija/ija2016/homework2/model/cards/*.java ija/ija2016/homework2/model/board/*.java
2nd you need to compile your test class (you will need to add to classpath what you just compiled and the junit.jar dependency): javac -d build -cp build;junit-4.12.jar ija/ija2016/HomeWork2Test.java
Now you can run your test class (in order to run you need to add to the classpath the build dir and the jar dependencies): java -cp build;junit-4.12.jar;hamcrest-core-1.3.jar org.junit.runner.JUnitCore ija.ija2016.HomeWork2Test
If you want to know more check JUnit 4 Doc
if you are using Linux or MacOS use ":" instead ";" between dirs in classpath

Categories

Resources