trustin / sphinx-gradle-plugin

Sphinx site generation plugin for Gradle
https://trustin.github.io/sphinx-gradle-plugin/
Apache License 2.0
18 stars 7 forks source link

Cannot generate plantuml diagrams #19

Open MaciejWadowski opened 4 years ago

MaciejWadowski commented 4 years ago

With gradle 6.5 and above running task does not generate uml diagrams. Error below:

WARNING: error while running plantuml

Exception in thread "main" java.lang.NoClassDefFoundError: org/gradle/internal/classpath/Instrumented
  at net.sourceforge.plantuml.cucadiagram.dot.GraphvizUtils.getenv(GraphvizUtils.java:151)
  at net.sourceforge.plantuml.cucadiagram.dot.GraphvizUtils.getenvDefaultConfigFilename(GraphvizUtils.java:143)
  at net.sourceforge.plantuml.Option.<init>(Option.java:111)
  at net.sourceforge.plantuml.Run.main(Run.java:89)
Caused by: java.lang.ClassNotFoundException: org.gradle.internal.classpath.Instrumented
  at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
  at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
  at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:352)
  at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
  ... 4 more
firthl commented 4 years ago

Have you tried pip installing graphviz on the system first? I don't believe it comes with plantuml directly - it probably needs to be on the path or pointed at via your sphinx config file.

MaciejWadowski commented 4 years ago

Ok my mistake, the documentation stop generating after 6.6 gradle version, 6.5.x still works well. I don't think that my configuration is bad if it's working on gradle 6.5.1.

trustin commented 4 years ago

Thanks for reporting. Just don't have enough time to look into this at the moment since I've just joined a company. Any pull requests would be appreciated.

jeff5 commented 3 years ago

I've been bitten by this too. My work-around is to generate documentation manually outside Gradle. I set plantuml in my own conf.py to use a JAR on my local machine. But it would be nice if it could be portable.

I have investigated, and I think I can pin-point the problem. I don't understand the mechanism at all really, or why upgrading Gradle brought it on. Fortunately, that's not the bit that needs fixing.

The error can be reproduced with particular versions of plantUML, alone, at the command prompt:

PS clean> java -jar plantuml-1.2020.4.jar testdot.uml
Exception in thread "main" java.lang.NoClassDefFoundError: org/gradle/internal/classpath/Instrumented
        at net.sourceforge.plantuml.cucadiagram.dot.GraphvizUtils.getenv(GraphvizUtils.java:151)
        ... 

Whereas:

PS clean> java -jar plantuml.1.2020.21.jar testdot.uml

gives me the image I'm entitled to.

Now, the Gradle plug-in depends on classes from the Sphinx-Maven plug-in, and that cites 1.2020.4 specifically https://github.com/trustin/sphinx-maven-plugin/blob/c28805c3e5d1c11d79d3e0d913eb6b11d284e1be/pom.xml#L93. This is one that exhibits the problem. I think updating this is the clean solution.

contrib-plantuml is simply picking up the plantuml command from configuration. The code that composes the command is at: https://github.com/trustin/sphinx-maven-plugin/blob/c28805c3e5d1c11d79d3e0d913eb6b11d284e1be/src/main/java/kr/motd/maven/sphinx/SphinxRunner.java#L86-L94. So the Maven plug-in finds the JAR via the class path, and having a newer Jar on the path ahead of the culprit may do the trick.

I am wondering if there is anything I can do in my Gradle script to force the version up to 1.2020.21?


PS. @trustin : this is awesome stuff, that I realise rests on the shifting sands of others' work. Thanks for doing it. I find it enormously helpful to be able to express my ideas in UML in Sphinx. After working this way most of the year, including to describe some structures inside CPython, I wonder how the Python core devs manage to communicate without using it.

trustin commented 3 years ago

Thanks everyone for your patience and kind words! I've just released a new version that depends on PlantUML 1.2021.1. Please let me know if the new version fixes your problem. :bow:

trustin commented 3 years ago

Unfortunately, it still seems to have a problem. Let me take another look later.

trustin commented 3 years ago

Here's my analysis:

Since 6.5, Gradle instruments the code that intercepts various potentially important calls into the JARs in the dependency of a plugin. For example, System.getProperty() is redirected to a method in Instrumented. This is not a problem as long as the instrumented JAR is executed in the JVM run by Gradle, because the class Instrumented is available in the class path. However, in our case, we launch a new JVM with the instrumented PlantUML JAR. Because this new JVM doesn't have Gradle classes in the class, we get a NoClassDefFoundException.

There are a few options to fix this problem:

MaciejWadowski commented 3 years ago

Workaround:

  1. Download plantuml.jar to your project.
  2. define env 'plantuml' in task, like that: env 'plantuml', "java -jar ${projectDir}/src/main/resources/plantuml.jar"

Basically you have to define plantuml inside gradle task, not plugin, otherwise Exception will be thrown