javax.annotation.PreDestroy class not found in lenskit and jdk 10 - java

I'm working with lenskit and I receive this error
Exception in thread "main" java.lang.NoClassDefFoundError: javax/annotation/PreDestroy
at org.grouplens.grapht.LifecycleManager.registerComponent(LifecycleManager.java:52)
at org.grouplens.grapht.reflect.internal.ClassInstantiator.instantiate(ClassInstantiator.java:140)
at org.grouplens.grapht.Instantiators$ProviderInstantiator.instantiate(Instantiators.java:148)
at org.grouplens.grapht.Instantiators$MemoizingInstantiator.instantiate(Instantiators.java:184)
at org.lenskit.inject.NodeInstantiator$DefaultImpl.instantiate(NodeInstantiator.java:91)
at org.lenskit.inject.NodeInstantiator.apply(NodeInstantiator.java:70)
at org.lenskit.inject.NodeInstantiator$DefaultImpl.apply(NodeInstantiator.java:82)
at org.lenskit.inject.InstantiatingNodeProcessor.processNode(InstantiatingNodeProcessor.java:54)
at org.lenskit.inject.NodeProcessors.processNodes(NodeProcessors.java:92)
at org.lenskit.inject.RecommenderInstantiator.replaceShareableNodes(RecommenderInstantiator.java:113)
at org.lenskit.inject.RecommenderInstantiator.instantiate(RecommenderInstantiator.java:82)
at org.lenskit.LenskitRecommenderEngineBuilder.build(LenskitRecommenderEngineBuilder.java:144)
at org.lenskit.LenskitRecommenderEngineBuilder.build(LenskitRecommenderEngineBuilder.java:112)
at org.lenskit.cli.util.RecommenderLoader.loadEngine(RecommenderLoader.java:87)
at org.lenskit.cli.commands.GlobalRecommend.execute(GlobalRecommend.java:72)
at org.lenskit.cli.Main.main(Main.java:73)
Caused by: java.lang.ClassNotFoundException: javax.annotation.PreDestroy
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:582)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:190)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:499)
... 16 more
It says that the annotation.PreDestroy class wasn't found. But in my external library there is a java.xml.ws.annotation library which includes the javax.annotation file.
The place that it was called is here.
/**
* Register a component with the lifecycle manager. The component will be torn down when the lifecycle manager
* is closed, using whatever teardown the lifecycle manager institutes.
*
* #param instance The component to register.
*/
public void registerComponent(Object instance) {
if (instance == null) {
return;
}
if (instance instanceof AutoCloseable) {
actions.add(new CloseAction((AutoCloseable) instance));
}
for (Method m: MethodUtils.getMethodsListWithAnnotation(instance.getClass(), PreDestroy.class)) {
actions.add(new PreDestroyAction(instance, m));
}
}
I'm currently using intellij, and I've tried importing the javax.annotation jar file but it didnt work. I also tried putting this code
dependencies {
compileOnly group: 'com.google.code.findbugs', name: 'jsr305', version: '3.0.0'
compile group: 'org.jetbrains', name: 'annotations', version: '15.0'
}
but it still didn't work.

Looking at lenskit source on GitHub, it declares sourceCompatibility = '1.7' in build,gradle.
Downgrading JDK to 8 or 7 should do the trick and resolve the issue. since javax.annotations.PreDestroy seem to have been removed/updated in JDK 9 and later.
Beyond that, there may be other compatibility issues with a later JDK version due to the project's source compatibility mentioned above.

Related

JavaFX - ProviderNotFoundException: Provider not found

I am building my JavaFX application together with the required JVM (openjdk-18.0.2.1) components using in jlink.
The build script is almost no different from being created using IDEA by default.
import org.gradle.internal.os.OperatingSystem
plugins {
id 'java'
id 'application'
id 'org.openjfx.javafxplugin' version '0.0.13'
id 'org.beryx.jlink' version '2.25.0'
}
group 'com.prototype'
version '1.0'
repositories {
mavenCentral()
}
ext {
junitVersion = '5.9.0'
}
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(18))
}
//withSourcesJar()
}
tasks.withType(JavaCompile) {
options.encoding = 'UTF-8'
}
application {
mainModule = 'com.prototype.catassistant'
mainClass = 'com.prototype.catassistant.CatAssistantApplication'
}
javafx {
version = '18.0.1'
modules = ['javafx.controls', 'javafx.fxml', 'javafx.web']
}
dependencies {
// https://mvnrepository.com/artifact/org.jetbrains/annotations
implementation 'org.jetbrains:annotations:23.0.0'
implementation('org.controlsfx:controlsfx:11.1.1')
// https://www.benf.org/other/cfr/api/index.html
// https://mvnrepository.com/artifact/org.benf/cfr
implementation 'org.benf:cfr:0.152'
// https://mvnrepository.com/artifact/com.google.code.gson/gson
implementation 'com.google.code.gson:gson:2.9.1'
testImplementation("org.junit.jupiter:junit-jupiter-api:${junitVersion}")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${junitVersion}")
}
test {
useJUnitPlatform()
}
jlink {
imageZip = project.file("${buildDir}/distributions/app-${javafx.platform.classifier}.zip")
options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
jpackage {
def currentOs = OperatingSystem.current()
def imgType = currentOs.windows ? 'ico' : currentOs.macOsX ? 'icns' : 'png'
icon = "src/main/resources/java.$imgType"
if (currentOs.windows) {
installerOptions += ['--win-per-user-install', '--win-dir-chooser', '--win-menu', '--win-shortcut', '--vendor', 'Prototype']
imageOptions += ['--win-console',/* '--icon', 'src/main/resources/icon.ico'*/]
}
}
launcher {
name = 'CatAssistant'
}
}
jlinkZip {
group = 'distribution'
}
After building the image, I successfully run it and it works, but when it comes to working with jar files, I get an incomprehensible error: java.nio.file.ProviderNotFoundException: Provider not found
Everything works fine from IDEA. I am also confused by the fact that after the build, "(Unknown Source)" is written in the entire stacktrace instead of lines of code, if there is such a possibility, I would like to fix it.
Caused by: java.nio.file.ProviderNotFoundException: Provider not found
at java.base/java.nio.file.FileSystems.newFileSystem(Unknown Source)
at java.base/java.nio.file.FileSystems.newFileSystem(Unknown Source)
at com.prototype.catassistant#1.0/com.prototype.catassistant.helper.FileHelper.readJarFile(Unknown Source)
FileHelper#readJarFile
// https://stackoverflow.com/a/37413531/10663941
public static void readJarFile(JarFile jar) {
try (FileSystem system = FileSystems.newFileSystem(jar.getPath())) { // <- exception
for (Path directory : system.getRootDirectories()) {
try (Stream<Path> stream = Files.walk(directory)) {
stream.filter(Predicate.not(Files::isDirectory))
.forEach(path -> jar.addEntry(path, read(system.getPath(path.toString()))));
}
}
} catch (IOException ex) {
AlertUtil.showExceptionDialog(ex);
throw new RuntimeException(ex);
}
}
I need help in solving this problem
ProviderNotFoundException
Most likely the java.nio.file.ProviderNotFoundException error is caused by the jdk.zipfs module not being included in the run-time image created by jlink / jpackage1. That module is a "provider module" for the java.nio.file.FileSystemProvider SPI. As such, I suspect none of the other modules that are part of your application directly or indirectly require the jdk.zipfs module. Typically, modules do not requires provider modules, as that defeats the purpose of the uses / provides mechanism of the Java Platform Module System (see the links in the second solution below for an explanation).
There are three ways you can fix this:
Use --bind-services when invoking jlink. This will cause jlink to look at all the required modules to see if any of them uses an SPI. If they do, then it will look for all available modules which provides implementations of the SPI and include them. Unfortunately, this will cause a lot of other modules to be included in your custom run-time image that you don't necessarily need.
Modify your module-info descriptor to add a requires jdk.zipfs directive. However, as noted in the documentation, having an "application module" require a "provider module" is not recommended.
Include an --add-modules jdk.zipfs argument when invoking jlink. This will force jlink to include the jdk.zipfs module without the unfortunate side-effects of the previous two solutions. Personally, I recommend using this solution in your case.
Unkown Source
The "Unknown Source" bits in the stack trace are caused by the --strip-debug argument which, unsurprisingly, removes debugging information from the byte-code. That includes the source file names and line numbers. Having --strip-debug reduces the size of the compiled code, which is good for the deployment version of your application.
1. You've confirmed this.

Running jar results in ClassNotFoundException (Gradle)

So I'm relatively inexperienced on how gradle works, and I need some help getting my jar working. My application generates some files through the terminal. However, when I try to run the jar, it gives me an error.
build.gradle:
plugins {
id 'java'
}
group 'me.tl0x'
version '1.0'
repositories {
mavenCentral()
}
jar {
manifest {
attributes (
'Main-Class': 'me.tl0x.Main'
)
}
}
dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
implementation 'org.freemarker:freemarker:2.3.29'
implementation 'com.google.code.gson:gson:2.8.6'
implementation 'org.jline:jline:3.21.0'
implementation 'org.fusesource.jansi:jansi:2.4.0'
}
test {
useJUnitPlatform()
}
Error Message:
PS C:\Path> java -jar ./build/libs/FabricModGenerator-1.0.jar
Exception in thread "main" java.lang.NoClassDefFoundError: org/jline/terminal/TerminalBuilder
at me.tl0x.terminal.Interface.<init>(Interface.java:29)
at me.tl0x.Main.main(Main.java:48)
Caused by: java.lang.ClassNotFoundException: org.jline.terminal.TerminalBuilder
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:636)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:182)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:519)
... 2 more
Any help would be greatly appreciated.
It's basically because your classpath doesn't include "jline" and the other stuffs required by your application.
Just use the application plugin and let that do the right thing (this is the right answer...)
But if it's a utility thing that you're doing...
Create a task that does the right thing and just run it via gradle (since you have no arguments)
def asFileUrl(filepath) {
return "file:///" + new java.net.URI(null, filepath, null).toASCIIString();
}
task LauncherJar(type: Jar) {
appendix = "launcher"
ext.launcherClasspath = { ->
def verifyLibs = [
configurations.runtimeClasspath.collect { asFileUrl(it.getCanonicalPath()) }.join(' '),
asFileUrl(jar.archivePath.getCanonicalPath())
]
return verifyLibs.join(' ')
}
manifest {
attributes ("Class-Path": launcherClasspath())
}
}
task execMyJar(type: JavaExec, dependsOn: [jar, LauncherJar]) {
group = 'Execution'
description = 'Do The thing that needs doing'
classpath = files(LauncherJar.archivePath)
mainClass = 'me.tl0x.Main'
}
Then you can just do gradle execMyJar.
Note that here, I'm creating a launcher jar with the Class-Path element in the Manifest file. The reason for that is to avoid the situation (Windows only?) where your command line is too long... It might not matter in your case since you haven't got that many dependencies listed (but I don't know about transitive dependencies).

Kotlin 1.4.30 Apache beam compilation error

I was trying to update to latest kotlin verion 1.4.30 an Apache Beam dataflow pipeline that is currently running with kotlin 1.4.21 but as soon as I upgrade build.gradle with version 1.4.30 the compilation fails with this exception:
java.lang.IllegalStateException: Could not read class: VirtualFile: /Users/stefanomassera/.gradle/caches/modules-2/files-2.1/org.apache.beam/beam-sdks-java-core/2.26.0/b57f8fa5ae66564c7ffafde34b690057f471bfa8/beam-sdks-java-core-2.26.0.jar!/org/apache/beam/sdk/options/PipelineOptions.class
at org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryJavaClass.<init>(BinaryJavaClass.kt:120)
at org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryJavaClass.<init>(BinaryJavaClass.kt:34)
at org.jetbrains.kotlin.cli.jvm.compiler.KotlinCliJavaFileManagerImpl.findClass(KotlinCliJavaFileManagerImpl.kt:115)
at org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade$CliFinder.findClass(KotlinJavaPsiFacade.java:484)
... omissis for brevity
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.IllegalArgumentException: Wildcard mast have a bound for annotation of WILDCARD_BOUND position
at org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryJavaAnnotation$Companion.computeTargetType$resolution_common_jvm(Annotations.kt:188)
at org.jetbrains.kotlin.load.java.structure.impl.classFiles.AnnotationsAndParameterCollectorMethodVisitor.visitTypeAnnotation$getTargetType(Annotations.kt:111)
at org.jetbrains.kotlin.load.java.structure.impl.classFiles.AnnotationsAndParameterCollectorMethodVisitor.visitTypeAnnotation(Annotations.kt:117)
at org.jetbrains.org.objectweb.asm.ClassReader.readMethod(ClassReader.java:1427)
at org.jetbrains.org.objectweb.asm.ClassReader.accept(ClassReader.java:719)
at org.jetbrains.org.objectweb.asm.ClassReader.accept(ClassReader.java:402)
at org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryJavaClass.<init>(BinaryJavaClass.kt:115)
... 101 more
I've also tried with a blank dummy project just to verify if it is a compatibility error with current kotlin and apache beam and it seems a compatibility issue, here my dummy test
main.kt
package org.example
import org.apache.beam.sdk.Pipeline
import org.apache.beam.sdk.options.PipelineOptionsFactory
class DummyPipeline {
fun main(args: Array<String>) {
val options = PipelineOptionsFactory.fromArgs(*args)
.withValidation()
.`as`(DummyPipelineOptions::class.java)
val pipeline = Pipeline.create(options)
pipeline.run()
}
}
build.gradle
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.4.30' //<-- do not build
//id 'org.jetbrains.kotlin.jvm' version '1.4.21' // <-- correctly build
}
group 'org.example'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib"
implementation "org.apache.beam:beam-sdks-java-io-google-cloud-platform:2.26.0"
runtimeOnly "org.apache.beam:beam-runners-direct-java:2.26.0"
}
Did anyone solved this compatibility issue?
It causes by the Kotlin compiler.
Sorry for nuisance, I'm currently fixing that on the compiler's side. The fix will be available in Kotlin 1.5-M1.
Unfortunately, there are no normal workarounds here, since the problem occurs when reading class files (it's impossible to exclude the problematic logic in the mechanism for reading class files).

gradle Jigsaw module not found

I try to run a very simple gradle project which uses java 9 modules, but i receive the following error.
/home/vadim/IdeaProjects/test_modules/src/main/java/module-info.java:2: error: module not found: HdrHistogram
requires HdrHistogram;
^
Here is it https://github.com/vad0/test_modules.
The main class does basically nothing.
package app;
import org.HdrHistogram.Histogram;
public class RunHdr {
public static void main(String[] args) {
final Histogram histogram = new Histogram(5);
System.out.println(histogram);
}
}
It uses only one dependency: HdrHistogram. I included this magic command in build.gradle according to official gradle tutorial https://docs.gradle.org/current/samples/sample_java_modules_multi_project.html.
java {
modularity.inferModulePath = true
}
The whole build.gradle looks like this.
plugins {
id 'java'
}
group 'org.example'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
java {
modularity.inferModulePath = true
}
dependencies {
compile group: 'org.hdrhistogram', name: 'HdrHistogram', version: '2.1.12'
testCompile group: 'junit', name: 'junit', version: '4.12'
}
module.info looks like this
module test.modules.main {
requires HdrHistogram;
}
I have already read a number of tutorials on Jigsaw and a whole bunch of stackoverflow questions related to it, but still can't make this simple example work. How do i fix it?
Thank you
Unfortunately, gradle does not treat every jar as a module (in simple words). If you want to find out how exactly is gradle building the module-path (as opposed to class-path), you probably want to start from here, specifically at the isModuleJar method. It's pretty easy to understand (though it took me almost two days to set-up gradle and debug the problem out) that the dependency that you are trying to use : gradle says that it is not a module (it isn't wrong, but I am not sure it is correct either). To make it very correct, gradle will add your dependency to the CLASSPATH, but in the very next line: it will not add your dependency to the module-path, because if fails the filter in isModuleJar.
I do not know if this is a bug or not, or may be this is on purpose, but the solution is easy:
plugins.withType(JavaPlugin).configureEach {
java {
modularity.inferModulePath = true
}
tasks.withType(JavaCompile) {
doFirst {
options.compilerArgs = [
'--module-path', classpath.asPath,
]
classpath = files()
}
}
}
you add it to the path, on purpose. I will flag this as a defect and let's see what they have to say.
EDIT
Even better, use a plugin that is written by a gradle commiter:
plugins {
id 'java'
id 'de.jjohannes.extra-java-module-info' version "0.1"
}
And the easiest option on your case is to do :
extraJavaModuleInfo {
automaticModule("HdrHistogram-2.1.12.jar", "HdrHistogram")
}

Problem when auto generating gRPC stub files using Gradle

I've been asked to implement some gRPC classes for a college course, and have run into some problems when generating the java classes from one source proto file.
Some background first: it's a fairly basic service, with a simple method that receives an id and returns a phone and an email. This is the proto file (BuscarData means FetchData, sorry for the leftover non translation!):
syntax = 'proto3';
option java_multiple_files=true;
option java_generic_services= true;
package uy.edu.um.sd20;
message DataRequest {
int32 id = 1;
}
message DataResponse {
string phone = 1;
string email = 2;
}
service DataRepo {
rpc BuscarData (DataRequest) returns (DataResponse);
}
The idea I had was to generate the classes with gradle plugins. My build.gradle:
plugins {
id 'java'
id "com.google.protobuf" version '0.8.8'
}
apply plugin: 'java'
group 'org.example'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
compile group: 'com.google.protobuf', name: 'protobuf-java', version: '3.11.4'
implementation 'io.grpc:grpc-netty-shaded:1.29.0'
implementation 'io.grpc:grpc-protobuf:1.29.0'
implementation 'io.grpc:grpc-stub:1.29.0'
}
sourceSets {
main {
proto {
srcDir 'src/main/proto'
}
java {
srcDirs 'src/main/java', 'generated-sources/main/java'
}
}
}
protobuf {
protoc {
artifact = 'com.google.protobuf:protoc:3.11.0'
}
plugins {
grpc {
artifact = 'io.grpc:protoc-gen-grpc-java:1.29.0'
}
}
generateProtoTasks.generatedFilesBaseDir = 'generated-sources'
generateProtoTasks {
all().each { task ->
// Here you can configure the task
}
ofSourceSet('main')
}
}
From what I understood, everything's there: the grpc and protoc dependencies, and the plugin which enables protoc to compile grpc (protoc-gen-grpc), and where to deposit the generated files.
However, there are two problems:
the generated-sources are not marked as source or anything like that, meaning they cannot be imported from other classes
if I'm not mistaken, the generated-sources should generate a skeleton of DataRepoImpl so that I can add the code needed for BuscarData. However, it didn't. Or maybe I should create it, extending from DataRepo.java, but I couldn't test it, due to problem n°1.
I've added a screenshot of the project file structure:
img
As you can see, quite a lot (if not all) of the gradle settings are copy-pasted and scavenged from many different web-sites. I hope I was careful enough not to repeat any imports. There are similar questions, and I tried the solutions there, but no luck there. One example, with which I knew I had to include the gen grpc plugin: another SO question
Any tip regarding anything else is welcome! I'm new to stackoverflow question-asking, so I may have made mistakes regarding the question specificity or aim of the question.
Thanks!
Franri.
For 1), the plugin should put the generated files are the input for java compile tasks even if you do not explicitly add 'generated-sources/main/java' in the sourceSets configuration. Version 0.8.8 has been a while, you can try with newer versions. There might have been some minor fixes for things you may hit.
For 2), you did not add grpc plugin to each generateProto task. It should be
generateProtoTasks {
all().each { task ->
task.plugins { grpc{} }
}
ofSourceSet('main')
}

Categories