I have been programming a java project using JDK14 and VSCode. Recently JDK15 is available, and I switched to the JDK. As for configuration, I pointed the VScode java.home and system JAVA_HOME to the new JDK folder.
When I clear the VSCode cache and restart the IDE, I started receiving this error
{
"resource": "/E:/dev/java/challenges/",
"owner": "_generated_diagnostic_collection_name_#3",
"code": "963",
"severity": 8,
"message": "Unbound classpath container: 'JRE System Library [JavaSE-15]' in project 'challenges'",
"source": "Java",
"startLineNumber": 1,
"startColumn": 1,
"endLineNumber": 1,
"endColumn": 1
}
I have seen similar questions/answers, but none of them was directed to VSCode.
https://stackoverflow.com/a/42525941/1005462
this one was helpfull;
replace :
build block in POM to
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
According to VsCode-Java in Twitter, JDK15 support won't be released until the end of September, and here is a github issue that's related to Java 15 not support.
I am new to building Java apps in VSCode. In my case, I was developing a microservice using Spring Boot. Here is what I've done to solve the issue ;
Make sure JAVA_HOME env variable is registered to the right path
Configured JDK path in java.jdt.ls.java.home to settings.json located inside .vscode. Here is my configuration.
{
"java.configuration.updateBuildConfiguration": "automatic",
"java.compile.nullAnalysis.mode": "automatic",
"java.jdt.ls.java.home": "/Library/Java/JavaVirtualMachines/temurin-11.jdk/Contents/Home"
}
Restart the VSCode
Related
I have JDK 7 and 8 installed in my PC.
I try to set JAVA_HOME to JDK 8 and in the maven pom file, I set to 1.7 as below:
<properties>
<maven.compiler.target>1.7</maven.compiler.target>
<maven.compiler.source>1.7</maven.compiler.source>
</properties>
I got the error below during maven build:
incomparable types: boolean and java.lang.Object
The source code is:
Map mapData = (LinkedHashMap)it.next();
if(true == mapData.get("isTrueOrFalse")){ // java 8 doesn't allow this, it have to be [true == (boolean)mapData.get("isTrueOrFalse")]
xxx
}
I can't change the source code, so I change my JAVA_HOME to JDK 7 and maven pom remain as 1.7. Then I can successfully build via Maven.
My understanding is, by setting the source and target, it should allow me to compile onto lower compatible Java version, but it is not. Can anyone help to explain this?
Apache Maven page says that:
Merely setting the target option does not guarantee that your code actually runs on a JRE with the specified version (...) In the same way, setting the source option does not guarantee that your code actually compiles on a JDK with the specified version
You could try first configuring the plugin directly (instead of what you have on pom.xml):
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<verbose>true</verbose>
<fork>true</fork>
<executable><!-- path-to-javac --></executable>
<compilerVersion>1.7</compilerVersion>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
Lastly, you can try Compiling Sources Using A Different JDK
After so many of searching of Java compatibility post, I found two possible reasons why this is happening:
1) this is a bug in JDK 7, it should not allow JDK 7 to compile this as the type is not match. This is fixed in JDK 8, so even we use the -source=1.7 and -target=1.7, it is not allowed to go through. JDK 1.7 breaks backward compatibility? (generics)
2) this might due to the Java implementation return type not compatible, while using JDK 8 compile to -source=1.7 and -target=1.7, the build path (bootstrap classes) will be still pointing to JDK 8, as so the implementation of Java Map may return different type which cause issue above. Issue about java 8 backward compatibility: new methods in JDK
Note Well
Please see the edit section of the question below, as further investigation has rendered the majority of this question redundant.
Similar to this question, I can't seem to pass environment variables to my app on startup while using VSCode. The problem is, I have no idea what (or if an) extension is causing the issue.
I have VSCode 1.38.1 with the following extensions;
Language support for Java 0.48.0
Java Extension Pack 0.8.0
Maven for Java 0.18.2
Spring Boot Dashboard 0.1.6
Spring Boot Tools 1.10.0
and several others that I don't feel are the culprits.
What I want to do is use maven profiles to conditionally bring in dependencies, and use environment variables to trigger that. In my pom.xml, I have;
<profiles>
<profile>
<id>dev-mysql</id>
<activation>
<!-- activate if system properties 'env=dev-mysql' passed in on launch.json env property from VSCode -->
<!-- Following does not work :( -->
<property>
<name>env</name>
<value>dev-mysql</value>
</property>
<!-- Obtain the following info by running - mvn enforcer:display-info -->
<!-- <os>
<name>windows 7</name>
<family>windows</family>
<arch>amd64</arch>
<version>6.1</version>
</os> -->
</activation>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.17</version>
</dependency>
</dependencies>
</profile>
</profiles>
I try and pass that env value in by setting it in launch.json via something like;
{
"type": "java",
"name": "Debug (Launch)-MyServiceApplication<my-service>",
"request": "launch",
"mainClass": "myapp.MyServiceApplication",
"projectName": "my-service",
"vmArgs": "-Dspring.profiles.active=local-mysql",
"env": {
"env": "dev-mysql"
}
}
I've also tried adding in maven customEnv through settings.json as the Maven for Java extension seems to suggest that "...These environment variable values will be added to the terminal session before Maven is first executed". My settings.json file looks like;
{
"java.configuration.updateBuildConfiguration": "automatic",
"files.exclude": {
"**/.classpath": true,
"**/.project": true,
"**/.settings": true,
"**/.factorypath": true
},
"maven.terminal.customEnv": [
{
"environmentVariable": "env",
"value": "dev-mysql"
}
]
}
I execute my application by hitting F5, which to my understanding executes what is shown in the launch.json snippet above. I don't quite understand how maven is invoked here. However, no matter what, it doesn't seem to ever find the environment variable and therefore include the profile specific mysql dependency. Even if I use Spring Boot Dashboard, I get the same result; the mysql dependency isn't recognised so I end up with Cannot load driver class: com.mysql.cj.jdbc.Driver
If I comment out the <property> element of my pom.xml and uncomment the <os> element, then it does bring in the profile specific mysql dependency. So I am guessing it uses the pom file correctly.
Does anyone have any clue how to set environment variables so that they'll be recognised with this configuation? Also, any further information as to what is actually executed when I hit F5 with this setup (is it maven, is it Java), it would be much appreciated.
Edit:
Some further investigation has shown that I was "...confusing Environment Variables with System Properties" comment by Wouter Lievens.
This post also suggests that "you cannot activate profiles based on system properties defined after the build plan has started execution", which may well be what happens when I just hit F5 to execute my application. This also links to some further information in this answer which clarifies that if won't work as "...profiles are the first thing evaluated before anything else to determine the effective POM.".
My workaround is to not use F5, but instead, when I have set the spring-profiles-active=local-mysql, I have to use the Maven for Java Explorer to execute a custom target of spring-boot:run -Pdev-mysql
So my last questions are;
Given the extensions I have added to VSCode combined with the above launch.json, what is actually executed when I hit F5 with this setup - is it Maven, Java or something else? If it is Java, how does the pom.xml come into play? If it is Java, is there a way of adjusting the launch.json to use mvn instead?
Is there a way to up the verbosity of the logging when I hit F5 to get a better understanding of what is actually being executed?
when running vscode driven tests, putting the environment variables in settings.json instead of launch.json works for me:
{
"java.configuration.updateBuildConfiguration": "automatic",
"java.test.config": [
{
"workingDirectory": "${workspaceFolder}",
"env": {
"STAGE_ENV": "DEV",
"AWS_REGION": "us-west-2"
}
}
]
}
however: maven tests do not read from this. I can run maven tests by adding the variables in the pom at this location:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
</plugin>
<plugin>
<!-- run unit tests -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
<configuration>
<environmentVariables>
<!-- add them here -->
<STAGE_ENV>DEV</AWS_ACCESS_KEY>
<AWS_REGION>us-west-2</AWS_REGION>
<!-- -->
</environmentVariables>
</configuration>
</plugin>
</plugins>
</build>
I have yet to find a good solution to use a single .env file to support both cases.
I'm starting to dig into Java 11 migration for a large app (includes Java FX parts) and I need your help to understand the difference between Maven (3.5.4) on the command-line and Eclipse (2018-09 with Java11 upgrade).
I have a simple Java 11 class
import java.util.stream.Stream;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.stage.Stage;
public class HelloFX extends Application {
#Override
public void start(Stage stage) {
String javaVersion = System.getProperty("java.version");
String javafxVersion = System.getProperty("javafx.version");
Label l = new Label("Hello, JavaFX " + javafxVersion + ", running on Java " + javaVersion + ".");
Scene scene = new Scene(l, 640, 480);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
Stream.of("jdk.module.path",
"jdk.module.upgrade.path",
"jdk.module.main",
"jdk.module.main.class").forEach(key -> System.out.println(key + " : " + System.getProperty(key)));
Application.launch();
}
}
and a simple pom
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.gluonhq</groupId>
<artifactId>hellofx</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>11</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<release>11</release>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>HelloFX</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
When I run 'mvn compile exec:java' I think nothing uses the new module-path and the program displays the JavaFX panel as expected.
The system out is:
jdk.module.path : null
jdk.module.upgrade.path : null
jdk.module.main : null
jdk.module.main.class : null
When ran from an Eclipse launcher, I have to add to the launcher the following vm arguments:
--module-path=${env_var:JAVAFX_PATH} --add-modules=javafx.controls
and the panel is also displayed but the output is:
jdk.module.path : C:\dev\tools\javafx-sdk-11\lib
jdk.module.upgrade.path : null
jdk.module.main : null
jdk.module.main.class : null
jdk.module.main.class : null
I cannot make it work in Eclipse as it works from the command line: I am forced to mess with the modules and module-path. If I do not add the vm parameters, I got either "Error: JavaFX runtime components are missing, and are required to run this application" or "Error occurred during initialization of boot layer java.lang.module.FindException: Module javafx.controls not found".
How can it work form the command-line without any more configuration ? To my knowledge Maven do not add automagically anything to the module path...
Any idea ? What am I missing ?
Update1: I realized that when importing the project in Eclipse "as Maven project" (which is what I always do) it results in the JRE being added in the module path (which is not the case for my classis projects). See the screenshot
When running from command line, if you are choosing the Maven (same works for Gradle) build system, you let the plugins do the work for you.
When you run from your IDE the main class, but not from the built-in Maven/Gradle windows, on the contrary, you are running the plain java command line options.
And these results in two different things (but with same final result of course), as you already have figured out via the properties print out.
As already covered by this answer for IntelliJ, but applies to any other IDE, or this other one for Eclipse, there are two ways of running a JavaFX 11 project, based on the use or not of the Maven/Gradle build system.
JavaFX project, without build tools
To run your JavaFX project from your IDE, you have to download the JavaFX SDK and add a library with the different javafx jars to your IDE, with a path like /Users/<user>/Downloads/javafx-sdk-11/lib/.
Now, to run that project, even if it is not modular, you have to add the path to those modules, and include the modules you are using to the VM options/arguments of the project.
Whether you run the project from your IDE or from command line, you will be running something like:
java --module-path /Users/<user>/Downloads/javafx-sdk-11/lib/ \
--add-modules=javafx.controls org.openjfx.hellofx.HelloFX
Note that even if your project is not modular, you are still using the JavaFX modules, and since you are not using any build tool, you have to take care of downloading the SDK in the first place.
JavaFX project, build tools
If you use Maven or Gradle build tools, the first main difference is that you don't need to download the JavaFX SDK. You will include in your pom (or build.gradle file) what modules you need, and Maven/Gradle will manage to download just those modules (and dependencies) to your local .m2/.gradle repository.
When you run your main class from Maven exec:java goal you are using a plugin, and the same goes for the run task on Gradle.
At this point, it looks like when you run:
mvn compile exec:java
or
gradle run
you are not adding the above VM arguments, but the fact is that Maven/Gradle are taking care of it for you.
Gradle
In the Gradle case, this is more evident, since you have to set them in the run task:
run {
doFirst {
jvmArgs = [
'--module-path', classpath.asPath,
'--add-modules', 'javafx.controls'
]
}
}
While you don't need the SDK, the classpath contains the path to your .m2 or .gradle repository where the javafx artifacts have been downloaded.
Maven
For Maven, while the pom manages the dependencies of the different javafx modules, and sets the classifier to download the platform-specific modules (see for instance /Users/<User>/.m2/repository/org/openjfx/javafx-controls/11/javafx.controls-11.pom), the plugin manages to configure the classpath and create the required options to run the project.
In short, a new class that doesn't extend Application is used to call your application class: HelloFX.main(args).
EDIT
See this answer for a more detailed explanation on why launching a JavaFX application without module-path fails. But in short:
This error comes from sun.launcher.LauncherHelper in the java.base module. The reason for this is that the Main app extends Application and has a main method. If that is the case, the LauncherHelper will check for the javafx.graphics module to be present as a named module. If that module is not present, the launch is aborted.
A more detailed explanation on how the maven plugin works without setting the module-path:
If you add debug level (default is info) when running the Maven goals, you will get more detailed information on what is going on behind the scenes.
Running mvn compile exec:java shows:
...
[DEBUG] (f) mainClass = org.openjfx.hellofx.HelloFX
...
[DEBUG] Invoking : org.openjfx.hellofx.HelloFX.main()
...
And if you check the exec-maven-plugin source code, you can find at ExecJavaMojo::execute how the main method of the Application class is called from a thread.
This is exactly what allows launching an Application class from an external class that does not extend Application class, to skip the checks.
Conclusion
Is up to you to choose build tools or not, though nowadays using them is the preferred option, of course. Either way, the end result will be the same.
But it is important to understand what are the differences of those approaches, and how your IDE deals with them.
My current project consisting of a war and ejb module, is using a jar (incorperated via maven). This jar contains a CDI component which, when I inject this in the war module it works as expected, but when I inject this in my ejb module I get a NoClassDefFoundError during startup from my WAS 8.5 in eclipse (full profile).
When I start the server first, add the inject later and republish it seems to work. Also when I use Liberty profile it works. Also on Z/os and IPAS it works as expected.
I think it might has something todo with classloading, but have no idea how to solve this properly.
Using Eclipse Neon, WAS 8.5.5.11 full profile , jee6
Project is using java 8 while the component is using java 6
This is the first part of the stacktrace:
[13-9-17 14:54:26:589 CEST] 0000003e InjectionProc W CWNEN0047W: Resource annotations on the fields of the BestelFacade class will be ignored. The annotations could not be obtained because of the exc
eption : Logger
at java.lang.Class.getDeclaredFieldsImpl(Native Method)
Thanks
I found a way to get the job done, but I'm not sure if this is a proper solution or just a workaround while masking the real problem.
When I take a look at the ear module assembly I see in the source column c:/ws/.../jar and in the deploy path lib/jar
when I change the source into /..ear/target/../jar it works
Try setting the <bundleDir>/</bundleDir>
This will place the external jar/ejb not in lib, but in the root.
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ear-plugin</artifactId>
<configuration>
...........
<defaultLibBundleDir>lib</defaultLibBundleDir>
<modules>
<jarModule>
<groupId>groupId</groupId>
<artifactId>artifactId</artifactId>
<bundleDir>/</bundleDir>
</jarModule>
</modules>
</configuration>
</plugin>
I normally use Google Cloud Endpoints on the AppEngine (Java) , as described in :
https://cloud.google.com/appengine/docs/java/endpoints/helloendpoints-java-maven
The dependency for the endpoints library I use is :
<plugin>
<groupId>com.google.appengine</groupId>
<artifactId>appengine-endpoints</artifactId>
<version>1.9.48</version>
</plugin>
Using this, I can start a local development server using the command:
mvn clean package appengine:devserver
However, there seems to be a new version of cloud endpoints.
https://cloud.google.com/endpoints/docs/frameworks/java/quickstart-frameworks-java .
The new framework is found here
<dependency>
<groupId>com.google.endpoints</groupId>
<artifactId>endpoints-framework</artifactId>
<version>${endpoints.framework.version}</version>
</dependency>
The same maven commands do not work here. I am unable to start a local dev server, open the API explorer or use a local datastore (all of which was possible earlier) . Could someone please guide me on how to work with the new framework.
Also, is the former framework likely to be deprecated ?
To answer my own question partially :
I could finally get the "Echo application" (mentioned in https://cloud.google.com/endpoints/docs/frameworks/java/quickstart-frameworks-java) to work
But I had to make 2 changes:
a) Comment out the block in appengine-web.xml . ie,
<!--
<basic-scaling>
<max-instances>2</max-instances>
</basic-scaling>
-->
After doing this, I got a different error, "failed endpoints-api-configuration: com.google.api.config.ServiceConfigException: Failed to fetch default config version for service"
To get around this :
b) Comment out the ServiceManagementConfigFilter from web.xml , ie,
<!--
<filter>
<filter-name>endpoints-api-configuration</filter-name>
<filter-class>com.google.api.control.ServiceManagementConfigFilter</filter-class>
</filter>
-->
<!--
<filter-mapping>
<filter-name>endpoints-api-configuration</filter-name>
<servlet-name>EndpointsServlet</servlet-name>
</filter-mapping>
-->
After this,
To build : mvn clean package
To run locally : appengine-java-sdk/1.9.44/appengine-java-sdk/appengine-java-sdk-1.9.44/bin/dev_appserver.sh /path/to/war/directory
It would be great if someone could shed more light on implication of these changes, and on how we could get it to work out of the box
There are a few problems you are running into and this stuff is overly sensitive to configuration issues:
To solve the problems follow the instructions in: https://cloud.google.com/endpoints/docs/frameworks/java/quickstart-frameworks-java
Use the correct Google project id when you replace the YOUR_PROJECT_ID in pom.xml. It needs to be a valid project id for all the steps to work.
Same when replacing the YOUR-PROJECT-ID in echo.java
If the project id is not valid (actually exists in AppEngine) the next steps won't work
execute: mvn exec:java -DGetSwaggerDoc
execute: gcloud service-management deploy openapi.json
execute: export ENDPOINTS_SERVICE_NAME=echo-api.endpoints.<your project id>.cloud.goog
The quickstart guide is not very helpful for step 5. Step 4 needs to end with a success message.
Finally the sample comes with a Maven plugin that does not seem to work with the new Endpoints.
Instead of using:
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>appengine-maven-plugin</artifactId>
<version>${appengine.maven.plugin.version}</version>
</plugin>
use:
<plugin>
<groupId>com.google.appengine</groupId>
<artifactId>appengine-maven-plugin</artifactId>
<version>1.9.44</version>
</plugin>
The answer to the question why mvn appengine:devserver doesn't work is that the devserver target doesn't exist in the new plugin.
The old Maven plugin allows you to execute: mvn appengine:devserver