“This is the sixth day of my participation in the First Challenge 2022. For details: First Challenge 2022”

Hello, I’m looking at the mountains.

After project today rely on a base component, start-up failure, screening process left some detours, confirm because ultimately depend on the component caused the Java version conflict. Lang. NoClassDefFoundError exception. The following is the investigation process, I hope to provide you with some ideas.

Observe the exception stack

Here is the printed exception stack information to extract possible key information, Could not convert argument value of type [java.lang.string] to Required type [java.lang.class] And “Unresolvable class definition for the class [cn. Howardliu. Demo. AddressMapper]”. Timing of continue to look for it from the exception stack, can be found is called AbstractAutowireCapableBeanFactory. CreateBeanInstance, this method is to create the Bean instance.

This is abnormal information (the content of the getMessage, transverse is too long, manual newline) : org. Springframework. Beans. Factory. UnsatisfiedDependencyException: Error creating bean with name'methodValidationPostProcessor' defined in class path resource [org/springframework/boot/autoconfigure/validation/ValidationAutoConfiguration.class] :Unsatisfied dependency expressed through method 'methodValidationPostProcessor' parameter 0;
    nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException:
    Error creating bean with name 'addressMapper'defined in file [/Users/liuxinghao/Documents/work/code/cn.howardliu/effective-spring/target/classes/cn/howardliu/demo/AddressMapper.clas s]: Unsatisfied dependency expressed through constructor parameter0:
    Could not convert argument value of type [java.lang.String] to required type [java.lang.Class]:
    Failed to convert value of type 'java.lang.String' to required type 'java.lang.Class';
    nested exception is java.lang.IllegalArgumentException: 
    Unresolvable class definition for class [cn.howardliu.demo.AddressMapper] Here is the exception stack:at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java: 799) ~ [spring-beans- 5.2.13.RELEASE.jar: 5.2.13.RELEASE]
	at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java: 540) ~ [spring-beans- 5.2.13.RELEASE.jar: 5.2.13.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java: 1341) ~ [spring-beans- 5.2.13.RELEASE.jar: 5.2.13.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java: 1181) ~ [spring-beans- 5.2.13.RELEASE.jar: 5.2.13.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java: 556) ~ [spring-beans- 5.2.13.RELEASE.jar: 5.2.13.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java: 516) ~ [spring-beans- 5.2.13.RELEASE.jar: 5.2.13.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0 (AbstractBeanFactory.java: 324) ~ [spring-beans- 5.2.13.RELEASE.jar: 5.2.13.RELEASE]
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java: 234) ~ [spring-beans- 5.2.13.RELEASE.jar: 5.2.13.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java: 322) ~ [spring-beans- 5.2.13.RELEASE.jar: 5.2.13.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java: 207) ~ [spring-beans- 5.2.13.RELEASE.jar: 5.2.13.RELEASEOther exception stack information can be ignoredCopy the code

We can according to the current effective information search, first take a look at our cn. Howardliu. Demo. AddressMapper define whether there is a problem, look at rely on its Service if you have any questions, also didn’t find any problem. The next checkpoint is configuration, such as whether @mapperscan is correct and annotated with @mapper on the Mapper class.

I can’t find the idea from the exception message, so I have to start with the code.

It needs to be mentioned here that printing abnormal information is very important, which directly affects our thinking of troubleshooting errors. If there is no way to accurately locate the printed message, we will spend a lot of time looking for the actual error, which requires code review and sometimes some experience.

Location problem

We by the exception stack ` ` ConstructorResolver. CreateArgumentArray (ConstructorResolver. Java: 799), follow the breakpoint chase down, Will eventually catch up with org. Springframework. Util. ClassUtils# class.forname method, which throws an exception of the code is the below:

try {
    return Class.forName(name, false, clToUse);
}
catch (ClassNotFoundException ex) {
    int lastDotIndex = name.lastIndexOf(PACKAGE_SEPARATOR);
    if(lastDotIndex ! = -1) {
        String innerClassName =
                name.substring(0, lastDotIndex) + INNER_CLASS_SEPARATOR + name.substring(lastDotIndex + 1);
        try {
            return Class.forName(innerClassName, false, clToUse);
        }
        catch (ClassNotFoundException ex2) {
            // Swallow - let original exception get through}}throw ex;
}
Copy the code

Error is Class. Class.forname (name, false, clToUse), the name travels is “cn. Howardliu. Demo. AddressMapper” string, Thrown exception is Java. Lang. NoClassDefFoundError, because not a ClassNotFoundException abnormal, not into the catch logic, can throw up directly.

Finding the error will help us locate the problem.

In general, Java. Lang. NoClassDefFoundError error is need to load classes can be found, but appeared when loading exception, simple said is that there is something wrong with the class definition. We run the jar with jD-GUI decompilation, and the result is as follows:

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import cn.howardliu.demo.Address;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface AddressMapper extends BaseMapper<Address{}
Copy the code

Observe carefully, we can see the import com. Baomidou. Mybatisplus. Core. Mapper. BaseMapper; This line is not underlined, which means that the interface is not traceable in the decompression tool, which means that the BaseMapper class definition is not found in the runtime environment.

. So, when the Class class.forname loading Class is thrown when the Java. Lang. NoClassDefFoundError exception.

To solve the problem

If you have any experience, you will immediately think that there is a high probability of jar-dependent version conflicts.

We can use the Maven command line to find conflicting dependencies:

mvn dependency:tree -Dverbose | grep conflict
Copy the code

The printed result is:

[the INFO] | + - (com baomidou: mybatis - plus: jar: 3.1.2: compile - omitted for conflict with 2.1.6)Copy the code

We can also use IDEA’s visualization tools to open the dependency graph on POM.xml:

We can see that the red line of MyBatis – Plus indicates the conflicting information:

The conclusion is that Mybatis-Plus version conflicts, the project relies on Mybatis-Plus 2.1.6 and 3.1.2 versions, because 2.1.6 path is shorter, finally selected.

In this case, you just need to remove the dependency of the earlier version.

Analyse the problem

Mybatis – Plus version issue

Why does a lower version of Mybatis – Plus cause class loading failures? Mybatis – Plus has changed the BaseMapper package path:

/ / 3.1.2 version
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/ / 2.1.6 version
import com.baomidou.mybatisplus.mapper.BaseMapper;
Copy the code

IService, ServiceImpl, TableName, TableField, Model, TableField, and many other commonly used classes have been relocated. This results in classes that cannot find dependencies. 3.1.2 Dependencies are still running in the environment, there will be no compilation problems, the execution of the loading class exception.

To solve this problem, we can create the base dependency BOM configuration and define the base dependency package without specifying the version in the project. In this way, the unified version can effectively avoid such problems.

We can also add conflicting dependency checks to CI/CD and terminate the pipeline if conflicting dependencies are found.

Real exceptions are hidden problems

Let’s look at why it is Java. Lang, a NoClassDefFoundError, abnormal results the stack is printed in a pile of incoherent mistake. Continue with the breakpoint Debug:

Org. Springframework. Util. ClassUtils# resolveClassName will capture LinkageError mistakes, then packaged into IllegalArgumentException exception, this time really is abnormal or go to throw.

Then in org. Springframework. Beans. TypeConverterSupport# convertIfNecessary method will be packaged into TypeMismatchException exception, at this point, the real anomalies also in abnormal cause parameters, It’s not lost.

Such as back to the org. Springframework. Beans. Factory. Support. ConstructorResolver# createArgumentArray method, after capturing anomalies of method is:

try {
    convertedValue = converter.convertIfNecessary(originalValue, paramType, methodParam);
}
catch (TypeMismatchException ex) {
    throw new UnsatisfiedDependencyException(
            mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam),
            "Could not convert argument value of type [" +
                    ObjectUtils.nullSafeClassName(valueHolder.getValue()) +
                    "] to required type [" + paramType.getName() + "]." + ex.getMessage());
}
Copy the code

At this point we can notice that when packaged into UnsatisfiedDependencyException abnormal, just stick to capture TypeMismatchException additional behind the abnormal description through the getMessage method, after the first few rounds of packaging and packaging, Real exception exception information remaining Unresolvable class definition for the class [cn. Howardliu. Demo. AddressMapper] the after processing of information, No Java. Lang. NoClassDefFoundError shadow.

So far, the real anomaly disappeared without trace.

This also gives us a reminder that we need to make sure that when we do get an exception, we need to keep valid information, otherwise, the error will be very troublesome.

At the end of the article to summarize

This article is to catch the worm, from the problem, to solve the problem, give a complete idea. Java. Lang. NoClassDefFoundError is usually appear in the version conflicts, this exception is compiled packaging is no problem, class is loaded at run time failure. The reason why we took some detours in the troubleshooting in this article is that Spring hid the real exception, which caused some obstacles to our troubleshooting. Therefore, we should also pay attention to clear information about exceptions in daily development, which can give us accurate goals for troubleshooting.

Green hills never change, green waters always flow. See you next time.

Recommended reading

  • This article describes 24 operations for Java8 Stream Collectors
  • Java8 Optional 6 kinds of operations
  • Use Lambda expressions to achieve super sorting functions
  • Java8 Time Library (1) : Describes the time class and common apis in Java8
  • Java8 time library (2) : Convert Date to LocalDate or LocalDateTime
  • Java8 Time Library (3) : Start using Java8 time classes
  • Java8 time library (4) : check if the date string is valid
  • New features in Java8
  • New features in Java9

Hello, I’m looking at the mountains. Swim in the code, play to enjoy life. If this article is helpful to you, please like, bookmark, follow.