Sharcoux
Sharcoux

Reputation: 6105

Can't make JSVGCanvas from Batik work in a Maven project

I spent 7h trying to make JSVGCanvas from Batik display a simple svg file. I can't make it work. The funny thing is that I always get different error messages given the versions of the dependencies I'm using. My last try gave me that :

java.lang.NoSuchMethodError: org.apache.batik.dom.svg.SVGDOMImplementation.createCSSEngine(Lorg/apache/batik/dom/svg/SVGOMDocument;Lorg/apache/batik/css/engine/CSSContext;)Lorg/apache/batik/css/engine/CSSEngine;
    at org.apache.batik.bridge.BridgeContext.initializeDocument(Unknown Source)
    at org.apache.batik.bridge.GVTBuilder.build(Unknown Source)
    at org.apache.batik.swing.svg.GVTTreeBuilder.run(Unknown Source)

and also sometimes :

Exception in thread "AWT-EventQueue-0" java.lang.NoClassDefFoundError: org/apache/batik/gvt/event/AbstractAWTEventDispatcher
Caused by: java.lang.ClassNotFoundException: org.apache.batik.gvt.event.AbstractAWTEventDispatcher
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:358)

But I already saw thousands of these errors, always about noSuchMethodException, or ClassNotFoundException, but it happens inside the batik classes and I don't succeed to attach the source so I can't even try to debug it...

My code is pretty simple :

public class Test {
    private static JFrame mainFrame;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                mainFrame = new JFrame("test");
                mainFrame.setSize(800,600);
                mainFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                mainFrame.setVisible(true);

                Container pane = mainFrame.getContentPane();
                pane.setLayout(new BorderLayout());
                JSVGCanvas canvas = new JSVGCanvas();
                canvas.setURI("file:///home/floz/NetBeansProjects/test/test.svg");
                pane.add(canvas, BorderLayout.CENTER);
            }
        });
    }
}

The code runs fine with normal dependencies, but if I use a Maven project it doesn't work. I tried to load the local jar, but I didn't get better results. Am I alone in this situation ?

Maven for batik : http://mvnrepository.com/artifact/org.apache.xmlgraphics

EDIT: I discovered that it works only if the dependancies respect a specific folder hierarchy. I didn't even knew it could make a difference as they all are imported... Anymay, I'm stuck because I don't know how to create a hierarchy with Maven... Any idea ?

EDIT2: I discovered svgSalamander that quickly fixed my problem for displaying svg. It's much lighter than JSVGCanvas

Upvotes: 1

Views: 1660

Answers (1)

Aaron Decker
Aaron Decker

Reputation: 168

The NoClassDefFoundError is likely because one of the batik jars is not in your classpath.

Here's one way to fix that in Maven:

  1. List the batik dependencies in pom.xml (assuming you have already done so)

  2. Add the following plugin to pom.xml

  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <configuration>
      <archive>
        <manifest>
          <addClasspath>true</addClasspath>
          <mainClass>com.mycompany.app.App</mainClass>
          <classpathPrefix>dependency/</classpathPrefix>
        </manifest>
      </archive>
    </configuration>
  </plugin>

The addClasspath lines tells Maven to add your dependencies to the classpath in the main manifest file in the jar it generates.

The mainClass line needs to delineate your main class.

The classpathPrefix tells Maven to add dependency/ to the front of the names of your dependencies' jars that it is putting on the classpath.

  1. Run mvn package to generate your jar. Maven will place it in ./target

  2. Run mvn dependency:copy-dependencies. This will cause Maven to download all of the dependencies' jar and place them in ./target/dependency, which is were the classpathPrefix was configured to look.

  3. java -jar ./target/whatever-your-jar-is-names.jar should then run properly.

Upvotes: 1

Related Questions