"java.lang.NoSuchMethodError" on Maven Install or Application Startup
Sample Error Message
java.lang.NoSuchMethodError: 'org.springframework.util.ReflectionUtils$MethodFilter org.springframework.util.ReflectionUtils$MethodFilter.and(org.springframework.util.ReflectionUtils$MethodFilter)'
If errors occur with the install or startup of the application that are due to missing methods from Spring Framework, one cause could be a scenario where multiple copies of Spring Framework libraries exist on the classpath.
To address this issue, first, use the Maven dependency plugin to look at the dependency graph and what packages are being used by the third-party libraries.
./mvnw dependency:tree
[INFO] --- dependency:3.3.0:tree (default-cli) @ sample-test ---
[INFO] com.example:sample-test:jar:0.0.1-SNAPSHOT
[INFO] +- com.herodevs.nes.apache.struts:struts2-spring-plugin:jar:2.5.33-struts2-2.5.34:compile
[INFO] | +- org.springframework:spring-beans:jar:4.3.26.RELEASE:compile
[INFO] | +- org.springframework:spring-core:jar:4.3.26.RELEASE:compile
[INFO] | | \- commons-logging:commons-logging:jar:1.2:compile
[INFO] | +- org.springframework:spring-context:jar:4.3.26.RELEASE:compile
[INFO] | | +- org.springframework:spring-aop:jar:4.3.26.RELEASE:compile
[INFO] | | \- org.springframework:spring-expression:jar:4.3.26.RELEASE:compile
[INFO] | +- org.springframework:spring-web:jar:4.3.26.RELEASE:compile
[INFO] | +- org.apache.commons:commons-lang3:jar:3.12.0:compile
[INFO] | \- com.herodevs.nes.apache.struts:struts2-core:jar:2.5.33-struts2-2.5.34:compile
[INFO] | +- org.freemarker:freemarker:jar:2.3.32:compile
[INFO] | +- ognl:ognl:jar:3.1.29:compile
[INFO] | | \- org.javassist:javassist:jar:3.20.0-GA:compile
[INFO] | +- org.apache.logging.log4j:log4j-api:jar:2.17.2:compile
[INFO] | +- commons-fileupload:commons-fileupload:jar:1.4:compile
[INFO] | \- commons-io:commons-io:jar:2.6:compile
[INFO] +- com.herodevs.nes.springframework.boot:spring-boot-autoconfigure:jar:2.7.18-spring-boot-2.7.19:compile
[INFO] +- com.herodevs.nes.springframework:spring-core:jar:5.3.39-spring-framework-5.3.40:compile
In this case, the struts2-spring-plugin is also pulling in "org.springframework:spring-beans", "org.springframework:spring-core", etc. but also a copy of "com.herodevs.nes.springframework:spring-core" also exists in the dependency list.
One way to address this issue is to use an exclusion configuration for the struts2-spring-plugin dependency. The artifactId in the <exclude> tag can be a full artifact ID like spring-core or a wildcard "*".
Example:
<dependencies>
<dependency>
<groupId>com.herodevs.nes.apache.struts</groupId>
<artifactId>struts2-spring-plugin</artifactId>
<version>2.5.33-struts2-2.5.34</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.herodevs.nes.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>2.7.18-spring-boot-2.7.19</version>
</dependency>
<dependency>
<groupId>com.herodevs.nes.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.39-spring-framework-5.3.40</version>
</dependency>
</dependencies>
Run the the command to display the dependency tree again and verify your configuration.
./mvnw dependency:tree
[INFO] --- dependency:3.3.0:tree (default-cli) @ sample-test ---
[INFO] com.example:sample-test:jar:0.0.1-SNAPSHOT[INFO] +- com.herodevs.nes.apache.struts:struts2-spring-plugin:jar:2.5.33-struts2-2.5.34:compile
[INFO] | +- org.apache.commons:commons-lang3:jar:3.12.0:compile
[INFO] | \- com.herodevs.nes.apache.struts:struts2-core:jar:2.5.33-struts2-2.5.34:compile
[INFO] | +- org.freemarker:freemarker:jar:2.3.32:compile
[INFO] | +- ognl:ognl:jar:3.1.29:compile
[INFO] | | \- org.javassist:javassist:jar:3.20.0-GA:compile
[INFO] | +- org.apache.logging.log4j:log4j-api:jar:2.17.2:compile
[INFO] | +- commons-fileupload:commons-fileupload:jar:1.4:compile
[INFO] | \- commons-io:commons-io:jar:2.6:compile
[INFO] +- com.herodevs.nes.springframework.boot:spring-boot-autoconfigure:jar:2.7.18-spring-boot-2.7.19:compile
[INFO] +- com.herodevs.nes.springframework:spring-core:jar:5.3.39-spring-framework-5.3.40:compile
Verify the application builds successfully.
./mvnw install
Alternate Method
Alternatively, you can try our Maven dependency plugin to do this for you using the following configuration in the build plugins of the pom.xml file.
<build>
<plugins>
<!-- others removed for brevity -->
<plugin>
<groupId>com.herodevs.nes.maven</groupId>
<artifactId>nes-maven-dependency-plugin</artifactId>
<version>1.0.0</version>
<executions>
<execution>
<goals>
<goal>resolveDependencies</goal>
</goals>
</execution>
</executions>
<configuration>
<patterns>
<pattern>org\.springframework.*</pattern>
</patterns>
</configuration>
</plugin>
</plugins>
</build>
The above plugin uses a provided regex pattern to exclude the desired artifacts from the classpath during the build. This plugin configuration can also specify multiple "<pattern>" tags.