jsoup
jsoup copied to clipboard
Provide module-info.java for Java9+ users
I know you already provide an Automatic-Module-Name for Java9+ users but we would be better off with a multi-release JAR that exports a full-fledged module-info.java
because when using requires transitive org.jsoup
the compiler complains (warns) against exporting automatic modules.
Publishing a MultiRelease JAR using Maven should be relatively easy. See multiReleaseOutput
at https://www.baeldung.com/maven-multi-release-jars
Hit me up if you run into any problems and I'll take a look.
Hi @cowwoc - I gave this a try, but can't get it to work. Animal Sniffer is failing when it tests (either for Java 1.8 or for Android 10 signature -- the exception doesn't specify which signature is failing on which class.
Have pushed a PR - #1470. If you have any ideas I'd love to hear them. I flailed around in Maven trying to upgrade dependencies and trying to find similar issues but could not. I can't find any projects that have a multi release jar and are using Animal Sniffer, if we could find a reference I think that would probably solve the issue.
[ERROR] Failed to execute goal org.codehaus.mojo:animal-sniffer-maven-plugin:1.19:check (compile-java-8) on project jsoup: Execution compile-java-8 of goal org.codehaus.mojo:animal-sniffer-maven-plugin:1.19:check failed: This feature
requires ASM6 -> [Help 1]
org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.codehaus.mojo:animal-sniffer-maven-plugin:1.19:check (compile-java-8) on project jsoup: Execution compile-java-8 of goal org.codehaus.mojo:animal-sniff
er-maven-plugin:1.19:check failed: This feature requires ASM6
at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:215)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:156)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:148)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:117)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:81)
at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:56)
at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:128)
at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:305)
at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:192)
at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:105)
at org.apache.maven.cli.MavenCli.execute (MavenCli.java:957)
at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:289)
at org.apache.maven.cli.MavenCli.main (MavenCli.java:193)
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke (Method.java:567)
at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:282)
at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:225)
at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:406)
at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:347)
Caused by: org.apache.maven.plugin.PluginExecutionException: Execution compile-java-8 of goal org.codehaus.mojo:animal-sniffer-maven-plugin:1.19:check failed: This feature requires ASM6
at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo (DefaultBuildPluginManager.java:148)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:210)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:156)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:148)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:117)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:81)
at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:56)
at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:128)
at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:305)
at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:192)
at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:105)
at org.apache.maven.cli.MavenCli.execute (MavenCli.java:957)
at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:289)
at org.apache.maven.cli.MavenCli.main (MavenCli.java:193)
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke (Method.java:567)
at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:282)
at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:225)
at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:406)
at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:347)
Caused by: java.lang.UnsupportedOperationException: This feature requires ASM6
at org.objectweb.asm.ClassVisitor.visitModule (ClassVisitor.java:137)
at org.objectweb.asm.ClassReader.readModuleAttributes (ClassReader.java:754)
at org.objectweb.asm.ClassReader.accept (ClassReader.java:553)
at org.objectweb.asm.ClassReader.accept (ClassReader.java:401)
at org.codehaus.mojo.animal_sniffer.ClassListBuilder.process (ClassListBuilder.java:70)
at org.codehaus.mojo.animal_sniffer.ClassFileVisitor.processClassFile (ClassFileVisitor.java:197)
at org.codehaus.mojo.animal_sniffer.ClassFileVisitor.process (ClassFileVisitor.java:116)
at org.codehaus.mojo.animal_sniffer.ClassFileVisitor.process (ClassFileVisitor.java:96)
at org.codehaus.mojo.animal_sniffer.ClassFileVisitor.processDirectory (ClassFileVisitor.java:134)
at org.codehaus.mojo.animal_sniffer.ClassFileVisitor.process (ClassFileVisitor.java:112)
at org.codehaus.mojo.animal_sniffer.ClassFileVisitor.process (ClassFileVisitor.java:96)
at org.codehaus.mojo.animal_sniffer.ClassFileVisitor.processDirectory (ClassFileVisitor.java:134)
at org.codehaus.mojo.animal_sniffer.ClassFileVisitor.process (ClassFileVisitor.java:112)
at org.codehaus.mojo.animal_sniffer.ClassFileVisitor.process (ClassFileVisitor.java:96)
at org.codehaus.mojo.animal_sniffer.ClassFileVisitor.processDirectory (ClassFileVisitor.java:134)
at org.codehaus.mojo.animal_sniffer.ClassFileVisitor.process (ClassFileVisitor.java:112)
at org.codehaus.mojo.animal_sniffer.ClassFileVisitor.process (ClassFileVisitor.java:96)
at org.codehaus.mojo.animal_sniffer.ClassFileVisitor.processDirectory (ClassFileVisitor.java:134)
at org.codehaus.mojo.animal_sniffer.ClassFileVisitor.process (ClassFileVisitor.java:112)
at org.codehaus.mojo.animal_sniffer.maven.CheckSignatureMojo.apply (CheckSignatureMojo.java:366)
at org.codehaus.mojo.animal_sniffer.maven.CheckSignatureMojo.buildPackageList (CheckSignatureMojo.java:359)
at org.codehaus.mojo.animal_sniffer.maven.CheckSignatureMojo.execute (CheckSignatureMojo.java:251)
at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo (DefaultBuildPluginManager.java:137)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:210)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:156)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:148)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:117)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:81)
at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:56)
at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:128)
at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:305)
at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:192)
at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:105)
at org.apache.maven.cli.MavenCli.execute (MavenCli.java:957)
at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:289)
at org.apache.maven.cli.MavenCli.main (MavenCli.java:193)
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke (Method.java:567)
at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:282)
at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:225)
at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:406)
at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:347)
[ERROR]
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/PluginExecutionException
This issue is fixed by https://github.com/mojohaus/animal-sniffer/pull/91 which is in master
but has not yet been released.
Is there a way to get a version of Jsoup that works with java 9+?
I have been searching but have not found any instructions.
@jjanderson5 this packaging fix doesn't impact jsoup's compatibility with Java 9+ (which it does support). Please follow up on #1477.
This might be a good use case for using moditect to generate the module-info.java.
@jhy FYI, the latest version of animal-sniffer now contains the required Java 9 fix. Can you please retry with this version?
Thanks, yes I will have another go
I took another pass at this and got stuck with all the Surefire integration tests failing, despite adding a module-info.java for the tests. (And despite that it doesn't seem required, given that the regular Junit tests still pass).
Does anyone have an example existing library I can use as a reference that uses Maven and Surefire / Integration tests?
I've done extensive work on this with Log4j 2. You don't say what the problem is but in general:
- The unit tests must be in the same package space as the main source. The module-info.java more or less extends the base module-info.
- If you create test helper classes that are used by other modules then they must not overlap the package space of the main module and will need their own module-info.java.
- In the case Log4j 2 has where it creates a test jar the Maven team recommends that the test jar be created in a separate Maven module which will cause it to be named something like log4j-core-tests-2.xx.0.jar instead of log4j-core-2.xx.0-tests.jar,
- Doing item 3 implies that the log4j core unit tests would have to be test classes in the log4j-core-tests module.
- As you might imagine from the above, it would be recommended that integration tests be in their own Maven module such as log4j-core-its. Needless to say, this requires the packages in this module do not overlap with the log4j-core packages.
As you can tell, JPMS has seriously complicated builds.Right now the master branch of Log4j 2 is not yet following the advice above and has the test jar and unit tests all in the same module as the main source. Needless to say this causes quite a mess that an IDE won't understand as it requires the compiler plugin be invoked several times using odd lifecycle phases.
I should also point out that there is a bug in the compiler where if you are compiling with JPMS and you have a package like com.acme.book and you have a class named com.acme.Book the compile will fail on MacOS. This bug is fixed in a later version of Java - off the top of my head I can't recall if it is 15 or 16.
@rgoers thank you, that's very helpful!
@jhy My understanding is that you need to decide whether your tests are doing blackbox or whitebox testing. Once you figured that out, you have 3 options:
- Whitebox testing: Place tests and production code in the same package and run tests on the classpath (no
module-info.java
). - Blackbox testing: Place tests in a different package than production code and run tests on the modulepath.
- Whitebox testing on the modulepath: Place tests in a different package than production code and use the SharedSecrets mechanism (https://stackoverflow.com/q/46722452/14731) to access production code.
Reference: discussion with Surefire authors at https://issues.apache.org/jira/browse/SUREFIRE-1733?focusedCommentId=17127382&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-17127382
It's about a half year passed, any progress?
I've created a pull request (#1744) to make Jsoup a multi-release module.
any chance of getting that PR rebased and merged in?
Thanks all - I have implemented this in #2025.
It would be great if folks could test this out and report back with confirmation of success or any issues. Please report back on the PR #2025 (or a new issue if any problems) as there are a few duplicate issues for this. To use a snapshot, git pull && mvn install
, and use version 1.17.1-SNAPSHOT
in your project.
I installed 1.17.1-SNAPSHOT
and added requires org.jsoup;
to a module-info in a project. Added some code to parse html of a page and extract elements.
final org.jsoup.nodes.Document doc = Jsoup.parse(someHtmlString, someUrl);
doc.select("a[href]")
.stream()
.collect(Collectors.toSet());
Can confirm it worked as expected.
Thanks!