1

I have this Junit 5 test code:

@InjectMocks
ReportAssembler reportAssembler;

private ReportingReturnResponse reportingReturnResponse;
private ReturnReport returnReport;
private StaticPathLinkBuilder staticPathLinkBuilder;

@Test
public void testMergeReturnCompletesSuccessfully() {
    ReportingResource reportResource = reportAssembler.mergeReturn(returnReport, this.reportingResource);
    assertNotNull(reportResource.getReturnResource());
}

The called code:

public ReportingResource mergeReturn(ReturnReport returnReport, ReportingResource reportingResource) {
    Link link = staticPathLinkBuilder.linkTo(
        methodOn(ReturnController.class).getReturnById(
            returnReport.getAccount().getId(),
            returnReport.getReturn().getId())
    ).withSelfRel();

    return reportingResource;
}

public LinkBuilder linkTo(Object dummyInvocation) {
    LastInvocationAware lastInvocationAware = (LastInvocationAware) dummyInvocation;

    MethodInvocation methodInvocation = lastInvocationAware.getLastInvocation();

    StaticPathLinkBuilder staticPathLinkBuilder = getThis();
    return staticPathLinkBuilder.linkTo(methodInvocation.getMethod(), methodInvocation.getArguments());
}

The line return staticPathLinkBuilder.linkTo(methodInvocation.getMethod(), methodInvocation.getArguments()) throws an exception Caused by: java.lang.IllegalArgumentException: Cannot subclass final class java.lang.reflect.Method

How I can solve it?

The stacktrace:

org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class java.lang.reflect.Method: Common causes of this problem include using a final class or a non-visible class
    at org.springframework.aop.framework.CglibAopProxy.buildProxy(CglibAopProxy.java:237)
    at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:167)
    at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:110)
    at org.springframework.hateoas.server.core.DummyInvocationUtils.getProxyWithInterceptor(DummyInvocationUtils.java:207)
    at org.springframework.hateoas.server.core.DummyInvocationUtils$InvocationRecordingMethodInterceptor.invoke(DummyInvocationUtils.java:96)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:223)
    at jdk.proxy3/jdk.proxy3.$Proxy81.getMethod(Unknown Source)
    at com.util.StaticPathLinkBuilder.linkTo(StaticPathLinkBuilder.java:56)
    at com.util.StaticPathLinkBuilder.linkTo(StaticPathLinkBuilder.java:42)
    at com.assembler.ReportingAssembler.mergeReturn(ReportingAssembler.java:233)
    at com.assembler.ReportingAssemblerReturnTest.testMergeReturnCompletesSuccessfully(ReportingAssemblerReturnTest.java:50)
    at java.base/java.lang.reflect.Method.invoke(Method.java:580)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
Caused by: java.lang.IllegalArgumentException: Cannot subclass final class java.lang.reflect.Method
    at org.springframework.cglib.proxy.Enhancer.generateClass(Enhancer.java:653)
    at org.springframework.cglib.transform.TransformingClassGenerator.generateClass(TransformingClassGenerator.java:35)
    at org.springframework.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:26)
    at org.springframework.cglib.core.ClassLoaderAwareGeneratorStrategy.generate(ClassLoaderAwareGeneratorStrategy.java:76)
    at org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:366)
    at org.springframework.cglib.proxy.Enhancer.generate(Enhancer.java:575)
    at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.lambda$new$1(AbstractClassGenerator.java:107)
    at org.springframework.cglib.core.internal.LoadingCache.lambda$createEntry$1(LoadingCache.java:52)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
    at org.springframework.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:57)
    at org.springframework.cglib.core.internal.LoadingCache.get(LoadingCache.java:34)
    at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:130)
    at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:317)
    at org.springframework.cglib.proxy.Enhancer.createHelper(Enhancer.java:562)
    at org.springframework.cglib.proxy.Enhancer.createClass(Enhancer.java:407)
    at org.springframework.aop.framework.ObjenesisCglibAopProxy.createProxyClassAndInstance(ObjenesisCglibAopProxy.java:62)
    at org.springframework.aop.framework.CglibAopProxy.buildProxy(CglibAopProxy.java:228)
    at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:167)
    at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:110)
    at org.springframework.hateoas.server.core.DummyInvocationUtils.getProxyWithInterceptor(DummyInvocationUtils.java:207)
    at org.springframework.hateoas.server.core.DummyInvocationUtils$InvocationRecordingMethodInterceptor.invoke(DummyInvocationUtils.java:96)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:223)
    at jdk.proxy3/jdk.proxy3.$Proxy81.getMethod(Unknown Source)
    at com.util.StaticPathLinkBuilder.linkTo(StaticPathLinkBuilder.java:56)
    at java.base/java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:733)
    at org.mockito.internal.util.reflection.InstrumentationMemberAccessor$Dispatcher$ByteBuddy$ADlM6biV.invokeWithArguments(Unknown Source)
    at org.mockito.internal.util.reflection.InstrumentationMemberAccessor.invoke(InstrumentationMemberAccessor.java:251)
    at org.mockito.internal.util.reflection.ModuleMemberAccessor.invoke(ModuleMemberAccessor.java:55)
    at org.mockito.internal.creation.bytebuddy.MockMethodAdvice.tryInvoke(MockMethodAdvice.java:314)
    at org.mockito.internal.creation.bytebuddy.MockMethodAdvice$RealMethodCall.invoke(MockMethodAdvice.java:234)
    at org.mockito.internal.invocation.InterceptedInvocation.callRealMethod(InterceptedInvocation.java:142)
    at org.mockito.internal.stubbing.answers.CallsRealMethods.answer(CallsRealMethods.java:45)
    at org.mockito.Answers.answer(Answers.java:90)
    at org.mockito.internal.handler.MockHandlerImpl.handle(MockHandlerImpl.java:111)
    at org.mockito.internal.handler.NullResultGuardian.handle(NullResultGuardian.java:29)
    at org.mockito.internal.handler.InvocationNotifierHandler.handle(InvocationNotifierHandler.java:34)
    at org.mockito.internal.creation.bytebuddy.MockMethodInterceptor.doIntercept(MockMethodInterceptor.java:82)
    at org.mockito.internal.creation.bytebuddy.MockMethodAdvice.handle(MockMethodAdvice.java:134)
    ... 6 more
5
  • Included the complete stacktrace. Commented Mar 12 at 0:52
  • 1
    That's not the complete stacktrace. Where is the "Caused by" chain? Show it all to us ... not just excerpts. Commented Mar 12 at 1:36
  • 1
    What dependencies and versions are used by the project? Also include JDK version. Commented Mar 12 at 2:06
  • 2
    Hello Pedro, Basically the problem is that you are trying to get the method of an inner class that is declared as "final", that is what throws the error you receive, you can remove the "final" and you will not have problems Commented Mar 12 at 3:10
  • final is one of the two keywords in Java that should be used with care, only if we have a good reason to do so. The other one is static. Commented Mar 12 at 21:12

1 Answer 1

1

You are using sensitive API, that is not intended for public use while it is public.
The library authors explain this in this GitHub issue.
They also suggest a workaround in the same github issue - use DummyInvocationUtils.getLastInvocationAware(...).

For your specific case, replace this:

LastInvocationAware lastInvocationAware = (LastInvocationAware) dummyInvocation;

with:

LastInvocationAware lastInvocationAware = DummyInvocationUtils.getLastInvocationAware(dummyInvocation);
Sign up to request clarification or add additional context in comments.

1 Comment

I have written the same answer stackoverflow.com/a/79515987/7613649. The author brought the current issue to another question. I would suggest to keep the current answer here because it correlates with the current question. And edit stackoverflow.com/questions/79494951/….

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.