0

I have a Maven project with only one dependency :

<dependency>
        <groupId>net.sf.jasperreports</groupId>
        <artifactId>jasperreports</artifactId>
        <version>6.8.0</version>
</dependency>

I am using an IDE and it installed all the required dependencies itself. I have written a simple code that uses the classes from net.sf.jasperreports. To create a the package I did mvn package and it created the jar. When I try to run the jar as java -jar myjar.jar, I get an error saying Caused by: java.lang.ClassNotFoundException: net.sf.jasperreports.engine.JRDataSource

I cannot understand how to resolve this. The IDE is able to find the classes but when invoked from command-line, it fails to find the classes. Why is that? What should I do?

I even tried to keep the jasperreports-6.8.0.jar at /Library/Java/Extensions/ but that too did not work.

Here is how the pom.xml looks like:

    <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
                            http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>
    <groupId>com.suhail</groupId>
    <artifactId>JasperCSVDataSource</artifactId>
    <version>1.0-SNAPSHOT</version>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>3.0.2</version>
                <configuration>
                    <archive>
                        <manifest>
                            <mainClass>com.suhail.main.CommandLineRunner</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <packaging>jar</packaging>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>

        <dependency>
            <groupId>net.sf.jasperreports</groupId>
            <artifactId>jasperreports</artifactId>
            <version>6.8.0</version>
        </dependency>

    </dependencies>    

</project>
halfer
  • 19,824
  • 17
  • 99
  • 186
Amanda
  • 2,013
  • 3
  • 24
  • 57
  • Is the class `JRDataSource` bundled in `myjar.jar,`? – J_D Apr 24 '19 at 07:54
  • This is because the libraries are not present in the compiled jar. You have to explicitly tell maven to include them in the build process. Have a look at the [maven shade plugin](https://maven.apache.org/plugins/maven-shade-plugin/) which can be used to create a *fat jar* having dependencies included. There may be different possibilities, but that's the one I use. – deHaar Apr 24 '19 at 07:55
  • @deHaar I have updated the question with `pom.xml`. Could you tell how could I use the `shade plugin`? – Amanda Apr 24 '19 at 07:57
  • @J_D I never mentioned it explicitly. Could you suggest a way on how I can? – Amanda Apr 24 '19 at 08:01
  • Please try [this](https://stackoverflow.com/questions/1729054/including-dependencies-in-a-jar-with-maven) link – J_D Apr 24 '19 at 08:26
  • 1
    If you do not want to assemble the dependencies yourself put keep the JARs separate: With Eclipse you could use the button in the run configuration which allows you to export the java commandline with all Requisites added as class and module path. – eckes Apr 24 '19 at 08:28

2 Answers2

0

This is the part that uses the maven shade plugin in my project, which is of course totally different from yours:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <version>3.2.1</version>
    <configuration>
        <source>1.8</source>
        <target>1.8</target>
    </configuration>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>shade</goal>
            </goals>
            <configuration>
                <shadedArtifactAttached>true</shadedArtifactAttached>
                <artifactSet>
                    <includes>
                        <include>org.apache.poi:poi</include>
                        <include>org.apache.poi:poi-ooxml</include>
                        <include>org.apache.poi:poi-ooxml-schemas</include>
                        <include>org.apache.commons:commons-collections4</include>
                        <include>org.apache.xmlbeans:xmlbeans</include>
                        <include>org.apache.commons:commons-compress</include>
                    </includes>
                    <excludes>
                        <!-- Exclude main jar to avoid error 'Failed to create shaded artifact, 
                            project main artifact does not exist' -->
                        <exclude>${project.groupId}:${project.artifactId}</exclude>
                    </excludes>
                </artifactSet>
            </configuration>
        </execution>
    </executions>
</plugin>
<plugin>
    <artifactId>maven-assembly-plugin</artifactId>
    <version>3.1.1</version>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>single</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <appendAssemblyId>false</appendAssemblyId>
        <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
    </configuration>
</plugin>

Please note that this part of the pom.xml goes into the <plugins> ... </plugins> section, in my case it is below the maven compiler plugin and below the maven jar plugin. You can explicitly include certain dependencies or explicitly exclude certain ones.

The result will be 2 files in your target folder, I personally use the one that has the original name, the other one will have the original name extended by shaded or similar.

If you get an error stating No main manifest attribute in ... then change your configuration of the maven jar plugin as follows:

<configuration>
    <archive>
        <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
    </archive>
    <mainClass>com.suhail.main.CommandLineRunner</mainClass>
</configuration>
deHaar
  • 17,687
  • 10
  • 38
  • 51
  • Could you explain the format : `org.apache.poi:poi` ? Is this `groupId:artifactId`? – Amanda Apr 24 '19 at 08:11
  • Yes, I think it is... This is basically the folder structure where the downloaded artifacts are stored as local libraries in your maven configuration. – deHaar Apr 24 '19 at 08:20
  • I tried running the shaded jar produced and it gives an error saying `no main manifest attribute, in target/JasperCSVDataSource-1.0-SNAPSHOT-shaded.jar` – Amanda Apr 24 '19 at 08:21
  • It is already there for `maven-jar-plugin` in my pom.xml. Should I be running the shaded jar file? – Amanda Apr 24 '19 at 08:33
  • Try it... I can't tell you exactly – deHaar Apr 24 '19 at 08:41
  • Maybe you need the assembly plugin, too. See my edit (second plugin below shade), it is in my pom.xml as well... – deHaar Apr 24 '19 at 09:01
-1

Use Maven assembly plugin instead Maven jar plugin.

see what-are-the-differences-between-maven-jar-plugin-and-maven-assembly-plugin!

Maven assembly plugin creates a fully deployable package with all dependencies packed in it.

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>2.4.1</version>
                <configuration>
                    <!-- get all project dependencies -->
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                    <!-- MainClass in mainfest make a executable jar -->
                    <archive>
                      <manifest>
                        <mainClass>com.suhail.main.CommandLineRunner</mainClass>
                      </manifest>
                    </archive>

                </configuration>
                <executions>
                  <execution>
                    <id>make-assembly</id>
                    <!-- bind to the packaging phase -->
                    <phase>package</phase> 
                    <goals>
                        <goal>single</goal>
                    </goals>
                  </execution>
                </executions>
            </plugin>
  • It would been helpful if you could have given `pom.xml` similar to what I have posted in my question. Would help to spot things easily. – Amanda Apr 24 '19 at 08:38
  • I have modified it, add above code inside and remove old one. [See sample here](https://www.mkyong.com/maven/create-a-fat-jar-file-maven-assembly-plugin/)! – naveen.ccmsd Apr 24 '19 at 09:06
  • In target folder you will see two jar files now. ***JasperCSVDataSource-0.0.1-SNAPSHOT.jar*** and ***JasperCSVDataSource-0.0.1-SNAPSHOT-jar-with-dependencies.jar***. – naveen.ccmsd Apr 24 '19 at 09:21