1

spring boot version : 2.4.1

spring cloud version : 2020.0.0

My code

@Configuration
public class BaseConfig {

    @Bean
    public Module sortJacksonModule() {
        return new SortJacksonModule();
    }
}

my pom.xml dependency

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-commons</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-openfeign-core</artifactId>
</dependency>

my pom.xml plugin

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

When run with IntelliJ IDEA, it work well.

But when run with jar(by mvn clean package), it show

Caused by: java.lang.NoClassDefFoundError: feign/codec/EncodeException
        at org.springframework.cloud.openfeign.support.SortJacksonModule.setupModule(SortJacksonModule.java:47) ~[spring-cloud-openfeign-core-3.0.0.jar!/:3.0.0]
        at com.fasterxml.jackson.databind.ObjectMapper.registerModule(ObjectMapper.java:819) ~[jackson-databind-2.11.3.jar!/:2.11.3]
        at com.fasterxml.jackson.databind.ObjectMapper.registerModules(ObjectMapper.java:1021) ~[jackson-databind-2.11.3.jar!/:2.11.3]
        at org.springframework.http.converter.json.Jackson2ObjectMapperBuilder.configure(Jackson2ObjectMapperBuilder.java:712) ~[spring-web-5.3.2.jar!/:5.3.2]
        at org.springframework.http.converter.json.Jackson2ObjectMapperBuilder.build(Jackson2ObjectMapperBuilder.java:680) ~[spring-web-5.3.2.jar!/:5.3.2]
        at org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$JacksonObjectMapperConfiguration.jacksonObjectMapper(JacksonAutoConfiguration.java:101) ~[spring-boot-autoconfigure-2.4.1.jar!/:2.4.1]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_232]
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_232]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_232]
        at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_232]
        at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ~[spring-beans-5.3.2.jar!/:5.3.2]
        ... 113 common frames omitted
Caused by: java.lang.ClassNotFoundException: feign.codec.EncodeException
        at java.net.URLClassLoader.findClass(URLClassLoader.java:382) ~[na:1.8.0_232]
        at java.lang.ClassLoader.loadClass(ClassLoader.java:418) ~[na:1.8.0_232]
        at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:151) ~[demo-spring-core-11-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
        at java.lang.ClassLoader.loadClass(ClassLoader.java:351) ~[na:1.8.0_232]
        ... 124 common frames omitted

After study the error log, I found that feign.codec.EncodeException is optional dependency in spring-cloud-openfeign-core, so ClassNotFoundException is right behavior(optional dependency not include in final jar).

So my question is: Why IntelliJ IDEA can run without any error? I try both IntelliJ IDEA run and mvn spring-boot:run, both work fine.

update: add example

After more study, I found out this only happen when the class not called.

        try {
            System.out.println("not important code");
        } catch (Exception e) {
            throw new EncodeException("not exist class");
        }

In this example, the try catch never throw an exception. And the EncodeException class is in an optional dependency. This code run well in IntelliJ IDEA, but fail when run as java -jar xxx.jar

========== update again with minimal demo

I create a minimal demo to reproduce this issue.

  • a standalone demo-module
        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-core</artifactId>
            <version>10.10.1</version>
            <optional>true</optional>
        </dependency>
import feign.codec.EncodeException;

/**
 * Hello world!
 */
public class App {

    public void testOptional() {
        try {
            System.out.println("test");
        } catch (Exception e) {
            throw new EncodeException("never throw this");
        }
    }
}
  • demo spring project(create by spring initializr and add a dependency)
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.example</groupId>
            <artifactId>demo-module</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
@Component
public class MyMain implements ApplicationRunner {

    @Override
    public void run(ApplicationArguments args) throws Exception {
        new App().testOptional();
    }
}
min
  • 953
  • 1
  • 11
  • 23
  • How do you run the jar? Did you add all other libraries to the classpath? – jurez Dec 25 '20 at 09:57
  • @jurez just pure `java -jar XXX.jar`. And as I said, I think `ClassNotFoundException` is right, I just don't understand why IntelliJ IDEA work without any error. – min Dec 25 '20 at 09:58
  • @user1686407, see in your IntelliJ IDEA, it could be possible that particular class exists in the build path. so it runs. I am assuming this jar which you are executing is not a fat jar or uber-jar , then in that case, you need to provide the classpath while executing it. Had it been fat jar, it would have run as fat jar has all the dependencies in it. – Nish Dec 25 '20 at 10:16
  • The IDE and maven run add those dependencies as args to the command for you. But when you just run the jar, you are missing those args – Nin Dec 25 '20 at 10:17
  • Spring boot Maven plugin as well as IDE may add the optional classes to the classpath - which is specific to spring-boot behaviour. – Andrey Dec 25 '20 at 10:26
  • Take a look into your resulting `target` directory... there are usually two jar files one which is larger than the other where this is the one you have to start which is the one to be used for running from plain command line... – khmarbaise Dec 25 '20 at 12:19
  • @Andrey If Spring boot maven plugin do that, why it fail when it run as jar? I use `mvn package` to build my jar. Btw, I check my jar, it doesn't contain the optional lib. – min Dec 28 '20 at 06:41

2 Answers2

0

Inspect your project classpath in Idea ( CTRL-Alt-Shift-S ) - I daresay optional jar is somewhere on module compile classpath and it is enough to run your class in IDE - but not in standalone jar. Optional means in maven context that it is present on classpath while compiling, but not packed into resulting artifact.

Konstantin Pribluda
  • 12,329
  • 1
  • 30
  • 35
  • So IntelliJ IDEA not support optional dependency? – min Dec 28 '20 at 10:25
  • Wait, please check my updated question, the core reason is the class not called. So maybe classpath is not the problem here? – min Dec 28 '20 at 10:36
  • IDEA supports all types of dependency provided by maven ( compile, test, runtime, provided ) - with roughly the same semantics. How is the plugin dependency listed in your IDEA project? How it is listed in your pom ( mvn help:effective-pom will display it )? And your idea project may be out of sync with idea project – Konstantin Pribluda Dec 28 '20 at 10:59
  • Hi, plz check my question again, I add a minimal demo. I think there is something different between how IntelliJ IDEA run and java -jar . – min Dec 29 '20 at 06:41
0

There is an option called Enable launch optimization in IntelliJ IDEA run config, uncheck it and everything work as expected.

min
  • 953
  • 1
  • 11
  • 23