Harry
Harry

Reputation: 15

Getting java.lang.IncompatibleClassChangeError while running a test

Getting error as

java.lang.IncompatibleClassChangeError: class org.glassfish.jersey.server.internal.scanning.AnnotationAcceptingListener$AnnotatedClassVisitor can not implement org.objectweb.asm.ClassVisitor, because it is not an interface (org.objectweb.asm.ClassVisitor is in unnamed module of loader 'app')

package com.configuration;

import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.Test;

import static org.junit.Assert.assertEquals;

import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.container.*;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.Response;
import java.io.IOException;

public class EndpointLoggingListenerTest extends JerseyTest {

    private static final String APPLICATION_NAME = "EndpointApplication";
    private static EndpointLoggingListener applicationEventListener;

    @Override
    protected Application configure() {
        applicationEventListener = new EndpointLoggingListener("abc");
        final ResourceConfig resourceConfig = new ResourceConfig(MyResource.class);
        resourceConfig.register(applicationEventListener);
        resourceConfig.register(RequestFilter.class);
        resourceConfig.register(PreMatchingRequestFilter.class);
        resourceConfig.register(ResponseFilter.class);
        // resourceConfig.register(MyExceptionMapper.class);
        resourceConfig.setApplicationName(APPLICATION_NAME);
        return resourceConfig;
    }

    @Test
    public void testMatchedMethod() {
        final Response response = target().path("resource").request().get();
        assertEquals(200, response.getStatus());
        assertEquals("get", response.readEntity(String.class));
    }


    public static class RequestFilter implements ContainerRequestFilter {

        @Override
        public void filter(ContainerRequestContext requestContext) throws IOException {
        }
    }

    @PreMatching
    public static class PreMatchingRequestFilter implements ContainerRequestFilter {

        @Override
        public void filter(ContainerRequestContext requestContext) throws IOException {
        }
    }


    public static class ResponseFilter implements ContainerResponseFilter {

        @Override
        public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
        }
    }

    @Path("resource")
    public static class MyResource {

        @GET
        public String getMethod() {
            return "get";
        }

        @POST
        public void post(String entity) {
        }

        @Path("locator")
        public SubResource locator() {
            return new SubResource();
        }
    }


    public static class SubResource {
        @GET
        public String get() {
            return "sub";
        }
    }
}

Upvotes: 0

Views: 4083

Answers (1)

Thomas Bitonti
Thomas Bitonti

Reputation: 1234

Net, the class AnnotationAcceptingListener was implemented using a version of ClassVisitor, but a new implementation of ClassVisitor has been provided with changes which are not compatible with the Listener implementation.

This is because ASM changed the ClassVisitor implementation when introducing version 4.0. Before version 4.0, ClassVisitor was implemented as an interface. Starting with version 4.0, ClassVisitor became an abstract class. See: https://asm.ow2.io/versions.html, and in particular, this text:

11 September 2011: ASM 4.0 RC2 (tag ASM_4_0_RC2) ClassVisitor, MethodVisitor, etc interfaces replaced with abstract classes, in order to ensure backward binary compatibility in future ASM versions.

Either, you'll need to link in an earlier version of the ASM jar, or you'll need a new implementation of AnnotationAcceptingListener which is compatible with the new ASM APIs.

(Generally, an IncompatibleClassChange error will be reported based on the dependency of a particular class on another class, where the initial, dependent, class is expecting a particular characteristic of the other, dependency, class. For example, the dependent class might have been compiled while the dependent class was an interface, but the implementation of the dependent class was changed to be a concrete class. A load of the dependent class made against the initial version of the dependency class works fine. A load of the dependent class against the updated version of the dependency class fails with an exception.)

Upvotes: 3

Related Questions