I am try to migrate my current project to be able to compile and run it on java 9. I am trying first to just move a java8 based project to java9 without not much effort which means not moving to jigsaw basically.
The project structure is something like
myjava-service [myjava-service-parent] parent-pom with the following modules
- myjava-service
- myjava-service-common
- myjava-service-test
it compiles perfectly with mvn clean package and it runs when I execute that fat.jar
the nightmare starts when I try to run it using intellij,to run on intellij i have to set the module I want to execute which is myjava-service but then apparently intellij understand it as java 9 module and well a lot of split packages issues, classes not found and other issues that I am struggling to fix, so my question is there a way to run the service on intellij under the java 9 environment without the new java module system being triggered somehow?
for the record issues like
java.lang.module.ResolutionException: Modules javax.annotation.api and annotations export package javax.annotation to module javax.el
So, apparently someone stepped into the same issue that I was facing, so what happens is that when your service start by a class which is not part of your sources (in my case my service is started by Starter class from the Vertx jar) then IDEA end up using the module path instead of class path. luckily Intellij team was quite helpful, follow up the ticket
https://youtrack.jetbrains.com/issue/IDEA-187390 , for the next version IDEA will abstain from using module path when there is no module-info file in sources.
Also for those who need desperately run a service in java 9 there's a work around which is basically create a Main class and Invoke it inside the class that starts your service, in my Case it looked like
public class Start {
public static void main(String[] args) {
Starter.main(args);
}
}
Related
I've been trying to write Hello JavaFX app and faced with necessity consider about Java modules for starting the app.
F.e. javafx-maven-plugin's run goal produce such startup command:
[DEBUG] Executing command line: [C:\java\zulu14.29.23-ca-jdk14.0.2-win_x64\bin\java.exe,
--module-path, C:\.m2\repository\org\openjfx\javafx-base\14\javafx-base-14-win.jar;
C:\.m2\repository\org\openjfx\javafx-base\14\javafx-base-14.jar;
C:\.m2\repository\org\openjfx\javafx-controls\14\javafx-controls-14-win.jar;
C:\.m2\repository\org\openjfx\javafx-controls\14\javafx-controls-14.jar;
C:\.m2\repository\org\openjfx\javafx-graphics\14\javafx-graphics-14-win.jar;
C:\.m2\repository\org\openjfx\javafx-graphics\14\javafx-graphics-14.jar,
--add-modules, javafx.base,javafx.controls,javafx.graphics,
-classpath, D:\project\target\classes, org.pkg.pkg.App]
But my project's structure doesn't mention Java module functionality - I didn't have module-info.java file.
Why can't I put all above JARs in the app classpath and be happy?
F.e.:
C:\java\zulu14.29.23-ca-jdk14.0.2-win_x64\bin\java.exe
"-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.4\lib\idea_rt.jar=59556:C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.4\bin"
-Dfile.encoding=UTF-8
-classpath D:\project\target\classes;
C:\.m2\repository\org\openjfx\javafx-controls\14\javafx-controls-14.jar;
C:\.m2\repository\org\openjfx\javafx-controls\14\javafx-controls-14-win.jar;
C:\.m2\repository\org\openjfx\javafx-graphics\14\javafx-graphics-14.jar;
C:\.m2\repository\org\openjfx\javafx-graphics\14\javafx-graphics-14-win.jar;
C:\.m2\repository\org\openjfx\javafx-base\14\javafx-base-14.jar;
C:\.m2\repository\org\openjfx\javafx-base\14\javafx-base-14-win.jar
org.pkg.pkg.App
If I'm right and understand Packages and Modules spec correctly
module JARs defined in the classpath treated as unnamed modules
unnamed modules export all their packages, i.e. everything is visible in them
But I get an error
Error: JavaFX runtime components are missing, and are required to run this application
Could someoune please explain me where I'm wrong here, about how Java modules work?
Thanks in advance!
Warning: Although the below shows what you want is possible, placing the JavaFX modules on the class-path is not supported. This means you should place JavaFX on the module-path, even when your own code is non-modular.
You can put JavaFX on the class-path and completely ignore modules1. However, the one caveat is that your main class can no longer be assignable to javafx.application.Application2. The workaround is to create a separate main class that simply launches the JavaFX application. For example:
import javafx.application.Application;
public class Launcher {
public static void main(String[] args) {
// where YourApp.class is replaced with your Application class
Application.launch(YourApp.class, args);
}
}
1. Your can't really ignore modules completely. All code on the class-path ends up in the unnamed module and all the modules in the run-time image (i.e. the JDK/JRE) still function as named modules.
2. This is due to an implementation detail. Java contains code which allows you to launch JavaFX applications without a main method, so long as the main class is assignable to Application. But when it detects that the main class is assignable to Application it checks for javafx.graphics in the boot ModuleLayer—meaning it must be on the module-path—and if not there then it assumes JavaFX is missing.
This is my base module which needs implementations of interfaces defined in myspi package. Various providers can offer MyProvider implementations. Base module uses them via myspi.MyProvider interface implementation.
module base {
exports myspi;
uses myspi.MyProvider;
}
This is my sample implementation module which provides the MyProvider implementation with MyProviderImpl
module myspi.provider {
provides myspi.MyProvider with myspi.provider.MyProviderImpl;
}
All these work fine when I load the implementations in base module, with
public static List<MyProvider> getMyProviders() {
var myProviders = new ArrayList<MyProvider>();
for (MyProvider myProvider : ServiceLoader.<MyProvider>load(MyProvider.class)) {
myProviders.add(myProvider);
}
return myProviders;
}
But same code returns empty list in Junit 5 test code (ServiceLoader returns null). How can I test the service provider modules with Junit 5. Or is there any alternative to Junit that allows us to create test modules (modularized test API) that declares "uses myspi.MyProvider" in the module-info and works fine with getMyProviders()?
Basically you're on the right track. You need to convince the Java module system that your test modules are the single source of thruth when it comes to resolve modules are test runtime.
Black-box testing is easy.
White-box testing in the modular world, meaning testing protected and package private members within a module, is tricky. There are at least two ways to achieve this: a) use java command line options to configure the Java module system at test startup or b) blend main sources into the test sources at compile time and maintain a dedicated module-info.java in your test sources.
Please visit the links to the blogs and examples posted over at How to make a modular build with jdk > 1.8
Here is an excerpt for convenience:
Examples
Work-in-progress blueprint https://github.com/sormuras/sandbox/tree/master/sors-modular-testing-blueprint
Integration tests starting with "modular-world-" at https://github.com/sormuras/junit-platform-maven-plugin/tree/master/src/it
Background and other resources
https://github.com/junit-team/junit5-samples/tree/master/junit5-modular-world
https://github.com/forax/pro
https://blog.codefx.org/java/five-command-line-options-to-hack-the-java-9-module-system/
And expect most IDE to not support you either. For now.
SOLVED!
I've removed the Junit from class-path to module-path and also removed all Junit 4 compatibility stuff such as RunWith() etc, and made my test pure Junit 5 test.
I've added a module-info.java (Junit 5 doesn't require an open module although the books tell the opposite)
After I've modularized the tests I found that it still doesn't execute the ServiceLoader stuff. Then I've started looking for the fault myself.
And I found it! Running the ServiceLoader stuff in base module was possible, because the base module refers to the exported myProvider.jar, which in turns access a myProvider-config.properties file in the same directory. Without this config file myProvider cannot work properly.
The problematic test module on the other hand, refered the eclipse project of the myProvider instead of its exported .jar file and hence could not find its config file and exits. I'd moved this config file from Netbeans to Eclipse simply copying it into the same directory. Thus missing config file was the problem.
Changing the project settings I could run the tests without any failure.
I would like to thank all the contributors who responded.
This is quite an old post but if anyone gets here trying to test java modules with junit 5 with gradle, especially the consumer/provider as presented in this post , Sormuras solution is the easy way, to patch the consumer module with the tests classes.
it is supported by gradle-modules-plugin that does that out of the box:
https://github.com/java9-modularity/gradle-modules-plugin
I am unable to compile tests with JUnit. When I attempt to do so, I get this error:
package org.junit.jupiter.api does not exist
I get this error compiling the tests even if I put the .jar in the same directory and compile as follows:
javac -cp junit4-4.12.jar Tests.java
The contents of Test.java are:
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
public class Tests {
... several tests ...
It's not clear to me what the issue is, and as far as I can tell, it should work with the .jar -- it's the one from /usr/share/java, where it was installed when I installed junit.
As #DwB has already mentioned you have wrong junit version.
Here is what is jupiter in JUnit: http://junit.org/junit5/docs/current/user-guide/#overview-what-is-junit-5
In simple words JUnit Jupiter API is a set of new classes which were written and introduced in junit 5 version only. And ur trying to use 4 version.
And also i want to clarify some points.
even if I put the .jar in the same directory and compile as follows
It does not matter actually is your file in the same directory or not. Its all about it's path. If you are setting jar only by name of jar file (as you did) then your path becomes relative to your current directory from where u execute javac command. You can just use absolute path and run this command from every directory you want.
https://docs.oracle.com/javase/8/docs/technotes/tools/windows/classpath.html (this one is for windows but for other os there are only minor changes in path writing)
If you get errors like package does not exist, classnotfound or anything similar then such kinds of errors almost always mean you have something wrong with your classpath or dependencies. In your case you simply had wrong version.
Now about finding necessary deps. In java world one of the main places for dependencies is maven central. Almost every opensource library can be found there and maven by default uses this repository to find and load dependencies (in your case these are jars) from there. Also you can use it to get necessary jars manually by simply using it's UI (https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api/5.0.0). There is download jar button.
Now if you know package or class but do not know in what dependency (jar for simplicity) it is located. In this case you can use http://grepcode.com or other resources which allow to search within available source code withit different repositories. In most cases this work. With juniper i did not manage to find smth there but in other cases this may help) Or the most simple case is just google package and in most cases it also will help to define entry point.
Now about solving ur issue. It seems that you will need as api as implentation. You will definitely need this one https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api/5.0.0 but it seems that you will need juniper-engine too. First try adding only API and then just go on adding necessary libraries according to errors. You can add multiple jars to cp (read provided class path guide from oracle).
I have a Scala project and I would like to export it as a jar.
*1. At first I tried creating a Java class for the project as an entry point
public class JMain {
public static void main(String[] args) {
System.out.println("Java main calling Scala main");
SMain.main(new String[] {""}); //SMain.main is the actual *main*
and this worked fine and dandy when launched from Eclipse, but when I export it as jar it'll give me 18 exceptions or so. I do now know how to replicate then "environment" in which Eclipse manages to launch this and I'm prety sure it relies on the fact that Scala is on my system already - I need a self contained jar with everything packed in there.
*2. My second try consisted of trying what lach suggested here How to deploy a Scala project from Eclipse?
namely:
public class JMain {
public static void main(String[] args) {
System.out.println("Java Main");
List<String> argList = new ArrayList<String>();
argList.add("fully.qualified.ClassName"); //???
for (String s : args) argList.add(s);
scala.tools.nsc.MainGenericRunner.main(argList.toArray(new String[0]));
This time it won't even run from Eclipse, although it gives only 6 or so exceptions starting with the famous NoClassDefFoundError. I have a feeling I'm not getting fully.qualified.ClassName right. *3. If the main Scala class is called "Dis.scala" and is located in package "pack" shouldn't this fully.qualified.ClassName be "pack.Dis"?
I'm using Jre 1.6 and Scala 2.9.2
EDIT: I have included all external imported jars, even scala-library.jar - everything is nice and packed in the jar
P.S. I am not familiar with Ant or Maven or Sbt. I just want my Scala project jared - if possible without getting into hairy things.
Here is what worked for me:
1. Create scala project
2. Create Wrapper java project
3. Add the scala-library.jar to you java project build path.
So you only need the 3rd step in addition since the rest looks similar to what I did. Then you can happily use: java - jar file.jar
EDIT:
How to create a JAR File which contains Scala/Code which can be consumed by another Java Project, using Scala - Eclipse IDE.
Create a new Scala Project and define an object with a main method as entry point.
Now create a new Java Project and add your Scala Project to the new ones buildpath. Additionally add the scala-library.jar to the Java project.
Now create a Wrapper class in the java project which calls your entry point class from the scala lib. Run the wrapper class to create a eclipse run configuration and test if you can call the scala project.
Use the Export->Java->Runnable JAR file, Wizard now on the wrapper project.The eclipse run configuration will be used as entrypoint into the JAR. Depending on your needs you may want to :
extract required libraries into generated JAR
or
Package required libraries into generated JAR
Finally you get a complete packaged JAR which you can use like this:
java - jar wrapped.jar
For me, it was relatively straightforward.
Develop and test the project using the scala IDE (or eclipse for java).
once ready, generate the jar for the project using file -> export method.
for submitting the spark (i was writing something for spark), i just had to mention --class option for specifying the main class for the jar.
hope to help.
I am building an Android hello world application in Netbeans. It's building properly and I am able to run in the emulator also.
But when creating and running the Junit test I get a java.lang.NoClassDefFoundError.
How can I fix this problem?
Check the manifest of your test project, for example HelloWorldTest/AndroidManifest.xml. The android:targetPackage attribute of the instrumentation markup should target the package in your application, for example, com.example.helloworld. Not the test package of your test project (eg. com.example.helloworld.test).
Simply AndroidManifest.xml -> manifest -> package of main application should match AndroidManifest.xml -> manifest -> instrumentation -> android:targetPackage of the test application.
The full error message contains the name of the class, that wasn't found on the classpath. Double check if the classpath that is used for running the test includes all required classes and libraries (your class files, junit.jar, android specific libaries).
I find that a rebuild usually finds the classes (as it is a classpath issue). Netbeans seems to aggressively compile existing tests, but the main source code (from a maven setting at least) is not always available.
I've started running full builds to try address this. There might be a plugin that addresses this but I haven't found it yet.
EDIT: This might help.
I don't know about netbeans specifics, but the problem is probably the same.
FragmentActivity can not be tested via ActivityInstrumentationTestCase2
Your test project can be using a different android compatibility library than your main project, and that causes this weird errors.