NoClassDefFoundError while packaging module with jar dependencies into archive-jar - java

I'm trying to create a utility jar which I can add to my other projects in the future to save some time while doing many of the same things over and over again.
Here is my project structure:
com.joul
--src
----some.package
------ClassImportingJOML.java
--module-info.java
--->requires org.joml;
exampleProject
--lib
----joul.jar
--src
----main
------Main.java
------->ClassImportingJOML c = new ClassImportingJOML();
I stumbled across modules and created my own. I make use of the org.joml module and mark it as a dependency in my module-info.java file. However, when I package this module into an archive-jar and add it to the module path of another project and run the code; I'm getting the same error: NoClassDefFoundError caused by ClassNotFoundException.
This only happens when I instantiate a class which imports that module. The exception is thrown in that class and not somewhere else. If anyone has any idea how I can create a jar such that exampleProject doesn't have to add org.joml to its dependencies please let me know, thanks!

Related

Modifying a library class by having a directory with the same path doesn't work in exported .jar

I have a gradle based project where I needed to make a few tweaks to some library classes. I made a package with the same path as the library to override the class. It ends up working fine in my IDE, but when I export it via packr, the application refers to the original library code, not my overridden package code, so I get errors like this.
class com.badlogic.gdx.utils.GdxRuntimeException: java.lang.NoSuchFieldError: soundCom
com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application.(Lwjgl3Application.java:172)
Sorry if there is terminology I am missing, I'm not too familiar with this process.
Found a solution!
Basically you add
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
to your dist task in desktop build.gradle

Compiling application with Tika with Java 13 - problems loading modules

I'm trying to migrate a Java application that uses Tika from OracleJDK 1.8 to OPenJDK 13.
My IDE is Eclipse.
I have created the file module-info.java to indicate the required modules for my application.
In order to be able to use Tika classes such as AbstractParser, Detector, etc., I have added requires org.apache.tika.core; in module-info.java.
My code also uses the class org.apache.tika.parser.pdf.PDFParserConfig to extract embedded images:
PDFParserConfig pdfConfig = new PDFParserConfig();
pdfConfig.setExtractInlineImages(true);
context.set(PDFParserConfig.class, pdfConfig);'
I get the compilation error:
PDFParserConfig cannot be resolved to a type
Eclipse suggests to add requires org.apache.tika.parsers; to module-info.java: Eclipse suggestion screenshot.
When I add this module requirement to module-info.java, the application compiles properly.
That is, at this stage we have included in module-info.java:
module myapp {
/** others ... */
requires org.apache.tika.core;
requires org.apache.tika.parsers;
}
However, when trying to execute the compiled application, we get the error:
Error occurred during initialization of boot layer
java.lang.module.FindException: Unable to derive module descriptor for C:\Users\Admin\.m2\repository\org\apache\tika\tika-parsers\1.24\tika-parsers-1.24.jar
Caused by: java.lang.module.InvalidModuleDescriptorException: Provider class org.apache.tika.parser.onenote.OneNoteParser not in module
Inspecting the project Libraries in Eclipse, I can see that tika-core and tika-parsers (v1.24) are both modular: Eclipse Java Build Path
In conclusion: If I don't add org.apache.tika.parsers as a required module, the application won't compile, and if I add it I get the runtime error saying org.apache.tika.parser.onenote.OneNoteParser is not in the module.
I have inspected the JAR files for these packages to see the dependencies they have. The core packages seems to be right:
$ jar --file=tika-core-1.24.jar --describe-module
No module descriptor found. Derived automatic module.
org.apache.tika.core#1.24 automatic
requires java.base mandated
contains org.apache.tika
contains org.apache.tika.concurrent
contains org.apache.tika.config
contains org.apache.tika.detect
contains org.apache.tika.embedder
contains org.apache.tika.exception
contains org.apache.tika.extractor
contains org.apache.tika.fork
contains org.apache.tika.io
contains org.apache.tika.language
contains org.apache.tika.language.detect
contains org.apache.tika.language.translate
contains org.apache.tika.metadata
contains org.apache.tika.mime
contains org.apache.tika.parser
contains org.apache.tika.parser.digest
contains org.apache.tika.parser.external
contains org.apache.tika.sax
contains org.apache.tika.sax.xpath
contains org.apache.tika.utils
...but the 'parsers' jar gives an error:
$ jar --file=tika-parsers-1.24.jar --describe-module
Unable to derive module descriptor for: tika-parsers-1.24.jar
Provider class org.apache.tika.parser.onenote.OneNoteParser not in module
Does this mean the jar package for parsers is not well formed?
Is there any workaround for this?
Thank you.
EDIT:
If I try with version 1.24.1, I get the execution error:
Error occurred during initialization of boot layer
java.lang.module.FindException: Unable to derive module descriptor for C:\Users\Admin\.m2\repository\org\apache\tika\tika-parsers\1.24.1\tika-parsers-1.24.1.jar
Caused by: java.lang.module.InvalidModuleDescriptorException: Provider class org.apache.tika.parser.external.CompositeExternalParser not in module
That is: the failing class is CompositeExternalParser instead of OneNoreParser.
Inspecting META-INF/services/org.apache.tika.parser.Parser of tika-parsers-1.42.1.jarI can see the entryorg.apache.tika.parser.external.CompositeExternalParser` but the package does not contain this class.
So, it seems to be an error in this META-INF file. Id this due to an error when compiling the package and submitting it to Maven Central?
I've found a JIRA issue, TIKA-2929, where they say "Apache Tika needs to be on the Java Classpath, not the module path". I've tried this, but, as explained before, I get a compilation error if I don't add it to the module path and set requires org.apache.tika.parsers;.
This is a hard puzzle...
Ran into the same issues.
Also found the faulty entries in
org.apache.tika.parser.Parser (and also org.apache.tika.parser.Detector) in META-INF/services/
A quick fix is to ...
Unpack those files
delete the lines that seem to reference non existing classes
pack them back into the jar
My project compiled after that.
For sure no longterm solution, but since even older versions i tried ran into that problem, it might help out some people.

How to add compile dependency to javadoc class path in gradle

In gradle if I my project depends on another package, for example:
compile 'com.example:foo:0.82.2'
And in my javadoc, it references symbol in that package.
Then if I run javadoc task, it will say error: reference not found
I know I should add that package to class path, just like the following way to add android library
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
But how could I know the classpath for my dependency except add a hard coding path point to the gradle cache?

Module dependency - package does not exist in compile time

I've read a lot of questions & answers in SO, without any luck. Example: Module packages not found at compile time in IntelliJ
The thing is that I've a project which formed by:
Module A
Module B
Module C
Module B has a dependency with module A and module C.
So the imports in module B, to code are like
import com.moduleA.Fragment1;
import com.moduleA.Fragment2;
import com.moduleA.SomeInterface;
Those lines are correctly imported in "coding-time", I can work with those classes correctly.
However when I do compile, it crashes with a:
Error:(8, 32) error: com.moduleA does not exist
I've tried adding this module A as Android Library but it's not OK for me, because Android requires generating constants fields (http://tools.android.com/tips/non-constant-fields).
I don't know what else to do.
Any tips?
Sorry for the people who asked for an example of code, but it was as basic as that, with a Gradle build.
I fixed the issue by creating a library project within my project. So module A is actually a Library.
I said that I couldn't use library because of the non-constant-field, but that error was generated by AndroidAnnotations, which explains how to create library modules with it:
https://github.com/excilys/androidannotations/wiki/Library-projects#referencing-ids-by-name
Thanks.

Grails 2.1.1 - How to develop a plugin with an AstTransformer?

I want to replace the auto injected log object, which is of type org.apache.commons.logging.Log with an object of type org.slf4j.Logger, so that I can use it properly with Logback.
Therefore I need to create a ...Transformer class (written in Java) - that's what I got from Graeme Rocher over at the "grails-user" mailing list. I'm also aware that I have to pack this ...Transformer class within a plugin and make it a *.jar archive which I can load within the lib/ folder of the plugin. But I guess I'm doing something wrong here as I have the class, along with a META-INF folder which contains the MANIFEST.MF file as well as another folder services which holds the following file org.codehaus.groovy.transform.ASTTransformation which holds just one String: the canonical name of the ...Transformer class.
Now, if I try to do a grails clean everything is fine, BUT if I try to run grails package-plugin the console comes up with a java.lang.ClassNotFoundException.
Clipping from Stacktrace:
| Packaging Grails application...
| Error Fatal error during compilation org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
Could not instantiate global transform class my.package.ast.LoggingTransformation specified at jar:file:/C:/Source/MyGrailsAST/lib/replace-logging-logback-ast.jar!/META-INF/services/org.codehaus.groovy.transform.ASTTransformation because of exception java.lang.ClassNotFoundException: my.package.ast.LoggingTransformation
1 error
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
Could not instantiate global transform class my.package.ast.LoggingTransformation specified at jar:file:/C:/Source/MyGrailsAST/lib/replace-logging-logback-ast.jar!/META-INF/services/org.codehaus.groovy.transform.ASTTransformation because of exception java.lang.ClassNotFoundException: my.package.ast.LoggingTransformation
Does anybody have some experience with Grails plugins which handle with AstTransformer and could give me some advice on this? Is there a good tutorial out there which I haven't seen so far?
Please let me know ;)
so, after some research, browsing and finally asking at the Grails Mailing List (see the mailing list archives at: http://grails.1312388.n4.nabble.com/Grails-user-f1312389.html I found a solution.
my goal was to create a Globals ASTTransformation, to inject a org.slf4j.Logger object instead of the usual org.apache.commons.logging.Log object into every Artefact class without annotation.
so, here are the steps:
I created Java class similar to https://github.com/grails/grails-core/blob/master/grails-logging/src/main/groovy/org/codehaus/groovy/grails/compiler/logging/LoggingTransformer.java but with my own implementation of the org.slf4j.Logger object. It is crucial that you place the Java.class under the following package: org.codehaus.groovy.grails.compiler as
Grails scans for classes that are annotated with #AstTransformer in this package. (Graeme Rocher)
and pack it into a JAR along with its MANIFEST.MF file within the META-INF/ folder. A META-INF/services directory with all its stuff is not needed as Graeme Rocher stated:
You do not need the META-INF/services stuff and I would remove it as it is probably complicating matters.
So, I guess this statement was more related to my specific problem as I only have one #AstTransformer class within my plugin, but that's just a guess. And I haven't searched for further informations on this topic. Maybe some other developer here who needs this could do some research and share his solution within this thread...
The JAR should be imported to the plugin and placed under the lib/ directory. After this you should be able to do grails clean, grails compile and grails package-plugin.
If you want to replace the log implementation, as I did, you should exclude the grails-logging and grails-plugin-log4j JARs from your designated project's classpath. This is done in the BuildConfig.groovy file:
inherits("global") {
excludes "grails-plugin-log4j", "grails-logging"
}
Now install your plugin grails install-plugin \path\to\plugin.zip and everthing should work as expected.
Hope this helps...

Categories

Resources