简体   繁体   中英

java-maven-idea: including external library in jar

I'm making telegram bot, and I need.jar to deploy it in cloud.
I'm building it with maven in intellij idea, but when trying to execute on my machine it throws this:

Exception in thread "main" java.lang.NoClassDefFoundError: org/telegram/telegrambots/bots/TelegramLongPollingBot<br>

As I've understood, this happens because maven doesn't packing this lib into.jar.
How can I do this?

Roughly speaking, you have two options

  1. Make a "fat" JAR with all required classes present
  2. Make a "thin" JAR that references other JAR files

What is most suitable for your situation is something only you can decide. Here's how you do it:

Make a "fat" JAR with all required classes present

To follow this approach, you use the Maven Shade Plugin . In the package phase, you would invoke its shade goal . That would copy classes from your dependencies as well as your application classes together into one JAR-file. It could look like this in the POM:

<executions>
  <execution>
    <goals>
      <goal>shade</goal>
    </goals>
    <configuration>
      <finalName>my-packaged-application</finalName>
      <transformers>
        <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
          <mainClass>com.mycompany.MyApplication</mainClass>
        </transformer>
      </transformers>
      <filters>
        <filter>
          <!--
            Shading signed JARs will fail without this.
            http://stackoverflow.com/questions/999489/invalid-signature-file-when-attempting-to-run-a-jar
          -->
          <artifact>*:*</artifact>
            <excludes>
              <exclude>META-INF/*.SF</exclude>
              <exclude>META-INF/*.DSA</exclude>
              <exclude>META-INF/*.RSA</exclude>
            </excludes>
          </filter>
        </filters>
      </configuration>
    </execution>
</executions>

The advantage of this approach is that your application gets packaged as one file. The disadvantage is that it's rather large. Even when you change just a few lines of code for a new version, the whole file will be different.

Make a "thin" JAR that references other JAR files

In this approach, the JAR only contains your application classes. Its manifest file references the classpath, but you need to also provide the JAR file for the dependencies. To collect those, use the Maven Dependency Plugin , more specifically the copy-dependencies goal . You configure it like so:

<executions>
  <execution>
    <id>copy</id>
    <phase>package</phase>
    <goals>
      <goal>copy-dependencies</goal>
    </goals>
    <configuration>
      <outputDirectory>${project.build.directory}/libs</outputDirectory>
      <stripVersion>true</stripVersion>
    </configuration>
  </execution>
</executions>

Now you have all dependency JAR files in target/lib , and the last thing is make sure that the "thin" JAR references those. To do so, configure the Maven Jar Plugin :

<configuration>
  <archive>
    <manifest>
      <addClasspath>true</addClasspath>
      <classpathPrefix>lib/</classpathPrefix>
      <mainClass>com.mycompany.MyApplication</mainClass>
    </manifest>
  </archive>
</configuration>

In this approach, if you change just a few lines of your application code, only the application JAR will be replaced - the dependency JARs are left intact. On the downside, it requires you to distribute not one file but a directory structure: the application JAR file as well as the lib/ folder with its contents.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM