user2608333
user2608333

Reputation: 71

NoSuchMethodError because wrong class is found

I have a Sprint Boot application and at deployment time I'm getting a NoSuchMethodError. I'm deploying to WebSphere 8.5.5.13. I'm pretty sure it's because the wrong class or version of the class is being found. It seems like the Spring code is looking for it's own class but is finding a class from the IBM jar file and the class it loads doesn't have an 'init()' method on it.

Please let me know if any further information will help determine a fix.

Here's my pom.xml file:

<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.companygoeshere</groupId>
    <artifactId>eacmanager</artifactId>
    <version>0.0.2-SNAPSHOT</version>
    <packaging>war</packaging>
    <name>EACManager</name>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-framework-bom</artifactId>
                <type>pom</type>
                <version>5.0.7.RELEASE</version>
                   <scope>import</scope> 
            </dependency>
        </dependencies>
    </dependencyManagement> 

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security.extensions</groupId>
            <artifactId>spring-security-saml2-core</artifactId>
             <version>1.0.4.RELEASE</version>
        </dependency>
         <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.jaxrs</groupId>
            <artifactId>jackson-jaxrs-base</artifactId>
        </dependency>
        <dependency>
            <groupId>ca.juliusdavies</groupId>
            <artifactId>not-yet-commons-ssl</artifactId>
            <version>0.3.11</version>
        </dependency>
        <dependency>
            <groupId>org.opensaml</groupId>
            <artifactId>opensaml</artifactId>
             <version>2.6.4</version>
        </dependency>
        <dependency>
            <groupId>com.microsoft.ews-java-api</groupId>
            <artifactId>ews-java-api</artifactId>
             <version>2.0</version>
        </dependency>

    </dependencies>

    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>

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

Here's the error message:

> com.ibm.ws.exception.RuntimeWarning:
> com.ibm.ws.exception.RuntimeWarning:
> com.ibm.ws.webcontainer.exception.WebAppNotLoadedException: Failed to
> load webapp: Failed to load webapp: Error creating bean with name
> &amp;#39&#59;defaultValidator&amp;#39&#59; defined in class path
> resource
> [org/springframework/boot/autoconfigure/validation/ValidationAutoConfiguration.class]:
> Invocation of init method failed&amp;#59&#59; nested exception is
> java.lang.NoSuchMethodError:
> javax/validation/Configuration.getDefaultParameterNameProvider&amp;#40&#59;&amp;#41&#59;Ljavax/validation/ParameterNameProvider&amp;#59&#59;
> &amp;#40&#59;loaded from file:/C:/Program Files
> &amp;#40&#59;x86&amp;#41&#59;**/IBM/WebSphere/AppServer/plugins/javax.j2ee.validation.jar** by
> org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader@3fb9923&amp;#41&#59;
> called from class
> org.springframework.validation.beanvalidation.LocalValidatorFactoryBean
> &amp;#40&#59;loaded from
> file:/C:/Program&amp;#37&#59;20Files&amp;#37&#59;20&amp;#40&#59;x86&amp;#41&#59;/IBM/WebSphere/AppServer/profiles/AppSrv01/installedApps/TheGarbers3Node01Cell/eacmanagerEAR.ear/eacmanager.war/WEB-INF/lib/spring-context-5.0.7.RELEASE.jar
> by 
> com.ibm.ws.classloader.CompoundClassLoader@79b97694[war:eacmanagerEAR/eacmanager.war]

Upvotes: 2

Views: 1321

Answers (3)

Daniel Treiber
Daniel Treiber

Reputation: 1487

To do this, you need to change the classloader of your application so the correct dependency is pulled in.

To do that via the UI, go to Applications -> WebSphere enterprise applications -> Your Application -> Class loading and update detection and change the Class loader order to be Classes loaded with local class loader first (parent last). This "causes the class loader to attempt to load classes from its local class path before delegating the class loading to its parent.".

If you are deploying an EAR and want this change to propagate to inner applications, you can either change WAR class loader policy to Single class loader for application or change the class loader of the individual war (in the EAR click Manage Modules -> Your Module then change Class loader order).

enter image description here

As long as you provide a version of dependency in question, you should get passed the above issue.

The following wasadmin.sh script will apply the above settings (replace app_name with the name of your application): (credit)

dep = AdminConfig.getid('/Deployment:app_name/');
depObject = AdminConfig.showAttribute(dep, 'deployedObject');
AdminConfig.modify(depObject, [['warClassLoaderPolicy', 'SINGLE']]);
classldr = AdminConfig.showAttribute(depObject, 'classloader');
AdminConfig.modify(classldr, [['mode', 'PARENT_LAST']]);

Upvotes: 1

Benjamin Lee
Benjamin Lee

Reputation: 11

Smells like a you have multiple versions of the same dependency on your classpath. You compile with one but you are running the other.

Run mvn dependency:tree and you can see everything you're bringing in. Often times transitive dependencies can cause the problems you're experiencing-- i.e, your webapp depends on both library Foo-v1 and Bar-v1. However, Foo-v1 itself depends on Bar-v2.

Once you find the duplicate library, try bumping each to be the same or latest version. Another approach is to try using maven's <exclusion></exclusion> so you only have one version of that library in your jar.

See this: https://maven.apache.org/guides/introduction/introduction-to-optional-and-excludes-dependencies.html

Upvotes: 0

Sundar
Sundar

Reputation: 16

Try changing the version of springboot in your pom.xml. It may work by referring different version of lib files

2.0.3.RELEASE --> 1.5-.59 etc

Upvotes: 0

Related Questions