Closed iranmarcius closed 3 years ago
I have the same problem with version 2.5.0.
org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.NoSuchMethodError: 'java.lang.String org.springframework.boot.web.servlet.error.ErrorController.getErrorPath()'
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1078)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:626)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at org.springframework.test.web.servlet.TestDispatcherServlet.service(TestDispatcherServlet.java:72)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)
at org.springframework.mock.web.MockFilterChain$ServletFilterProxy.doFilter(MockFilterChain.java:167)
at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:134)
at com.netcetera.girders.web.JSessionIdFilter.doFilter(JSessionIdFilter.java:55)
at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:134)
at org.springframework.web.filter.AbstractRequestLoggingFilter.doFilterInternal(AbstractRequestLoggingFilter.java:289)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:134)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:134)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:134)
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:96)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:134)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:134)
at org.springframework.test.web.servlet.MockMvc.perform(MockMvc.java:183)
at com.netcetera.mobaint.switcher.filter.FilterTest.shouldGetContractFromAccessTokenCookieAndRouteToMock(FilterTest.java:197)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:688)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:210)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:206)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:131)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:65)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:108)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:96)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:75)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:220)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:53)
Caused by: java.lang.NoSuchMethodError: 'java.lang.String org.springframework.boot.web.servlet.error.ErrorController.getErrorPath()' at org.springframework.cloud.netflix.zuul.web.ZuulHandlerMapping.lookupHandler(ZuulHandlerMapping.java:87) at org.springframework.web.servlet.handler.AbstractUrlHandlerMapping.getHandlerInternal(AbstractUrlHandlerMapping.java:152) at org.springframework.web.servlet.handler.AbstractHandlerMapping.getHandler(AbstractHandlerMapping.java:498) at org.springframework.web.servlet.DispatcherServlet.getHandler(DispatcherServlet.java:1257) at org.springframework.test.web.servlet.TestDispatcherServlet.getHandler(TestDispatcherServlet.java:122) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1039) ... 93 more
do you maybe know when fix version can be expected?
We are facing exactly the same issue with spring boot 2.5.1. Would someone help have a look at it? Thanks a lot.
I submitted a PR for this, but it was rejected as the 2.x branch does not support Spring Boot 2.5: https://github.com/spring-cloud/spring-cloud-netflix/pull/4012
I submitted a PR for this, but it was rejected as the 2.x branch does not support Spring Boot 2.5: #4012
Thank you for the info. Is there a way of fixing it outside the lib? For example, override this bean
@Bean
public ZuulHandlerMapping zuulHandlerMapping
And use a customised ErrorController?
We are also facing the same issue with 2.5.2. There is a question on StackOverflow for the same. We would appreciate a workaround till the time library starts supporting spring boot 2.5.2 officially.
After some googling I found that zuul and ribbon were removed from the springboot main channel in 2.5.x So you need to replace them with their alternatives
Having the same issue... Any news on this?
@chexmo not sure we need to replace it. They just went into maintenance mode, meaning new features wont be added.
Also, not sure how much of a replacement Spring Cloud Gateway
is since it uses webflux under the hood, which was not a pre-requisite for Zuul :/
Same problem here.
@clementdenis hope one day they decide to integrate your fix, meanwhile, after some investigation I was able to make it work, maybe it's a start point to patch it in your projects. Not a fully tested code, but I published this gist if anyone is interested, please see the gist's first comment (improvements are welcome!).
After all, I supose that will migrate our project to Spring Cloud Gateway...
Same issue :( Did anyone find a alternative solution for this issue ?
Hi @ajitesh-sivakumar, maybe you can try the gist in my comment above. I don't like this kind of solutions but It's working for me.
Quickly developed an alternative solution in this gist.
A BeanPostProcessor
creates a proxy around the original ZuulHandlerMapping
bean. The proxy intercepts the invocation of the lookupHandler
method preventing the execution of the code leading to NoSuchMethodError
.
@espartero , thanks. I will give it a try. I am worried that this might be temporary fix, but after Spring team (may) fix this bug in next update, it will crash my application.
Quickly developed an alternative solution in this gist. A
BeanPostProcessor
creates a proxy around the originalZuulHandlerMapping
bean. The proxy intercepts the invocation of thelookupHandler
method preventing the execution of the code leading toNoSuchMethodError
.
Looks very good! Didn't knew this way to override the beans, I'll try it.
Just comment that maybe we can also replace the ERROR_PATH constant by injecting:
@Value("${server.error.path:${error.path:/error}}")
to be equivalent to this.
@ajitesh-sivakumar I prefer @aldobongio solution, maybe you can try it.
Quickly developed an alternative solution in this gist. A
BeanPostProcessor
creates a proxy around the originalZuulHandlerMapping
bean. The proxy intercepts the invocation of thelookupHandler
method preventing the execution of the code leading toNoSuchMethodError
.
It worked..Thanks..
Closing as there is a workaround and Zuul is no longer supported by Spring Cloud.
Quickly developed an alternative solution in this gist. A
BeanPostProcessor
creates a proxy around the originalZuulHandlerMapping
bean. The proxy intercepts the invocation of thelookupHandler
method preventing the execution of the code leading toNoSuchMethodError
.
Thank you so much. Your fix worked for me :)
Thanks a lot @aldobongio !! Here a shortened version in Kotlin:
import org.springframework.beans.factory.config.BeanPostProcessor
import org.springframework.boot.web.servlet.error.ErrorController
import org.springframework.cglib.proxy.*
import org.springframework.cloud.netflix.zuul.filters.RouteLocator
import org.springframework.cloud.netflix.zuul.web.*
import org.springframework.context.annotation.*
/**
* Fix for Zuul configuration with Spring Boot 2.5.x + Zuul - "NoSuchMethodError: ErrorController.getErrorPath()"
*/
@Configuration
class ZuulSpringWorkaround {
@Bean
fun zuulPostProcessor(locator: RouteLocator, controller: ZuulController, errorController: ErrorController?) =
object : BeanPostProcessor {
override fun postProcessAfterInitialization(bean: Any, beanName: String) =
if (errorController != null && bean is ZuulHandlerMapping) {
val constructorTypes = ZuulHandlerMapping::class.java.constructors[0].parameterTypes
Enhancer().apply {
setSuperclass(ZuulHandlerMapping::class.java)
setCallbackFilter { if ("lookupHandler" == it.name) 0 else 1 }
setCallbacks(arrayOf(MethodInterceptor { target, _, args, proxy ->
if ("/error" == args[0]) null else proxy.invokeSuper(target, args)
}, NoOp.INSTANCE))
}.create(constructorTypes, arrayOf(locator, controller))
} else bean
}
}
@rkeytacked Thanks a bunch, saved me lots of time! :-)
Has anyone tested the fix on Spring Boot 2.6?
thanks a lot its working!
@andresestrella Doesn't seem to be working for 2.6.6 Did you try?
@andresestrella Doesn't seem to be working for 2.6.6 Did you try?
I did tried w/ Spring Boot 2.6.6, it's not working
Has anyone tested the fix on Spring Boot 2.6?
I did, it worked
Worked for me in Spring Boot 2.6.7 with:
cloud:spring-cloud-dependencies:2021.0.1
Make sure you still have @EnableZuulProxy
also.
We definitely discourage using Spring Cloud Zuul. The project is no longer maintained and there might be dependencies with vulnerabilities present. We encourage migrating to Spring Cloud Gateway instead.
@rkeytacked thanks a lot and share the junit test cases for the same class.
@pvraju1988 The tests for this configuration class are left as an exercise for junior engineers… :sunglasses:
Same problem using spring boot 2.7
Fix with BeanPostProcessor didn't work for me (I got "java.lang.IllegalStateException: No ServletContext set" due to some circular dependencies. I use Spring Boot 2.6.7, Spring Cloud 2021.0.3, spring-cloud-starter-netflix-zuul:2.2.10.RELEASE), so I wrote my own (hack, but works):
public class ZuulConfig2 implements ApplicationContextAware {
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (applicationContext.containsBean("zuulHandlerMapping")) {
applicationContext.getBean(ZuulHandlerMapping.class).setErrorController(null);
}
}
Pasting it here to help other people, who
BeanPostProcessor
fix (as me)A super simple fix/hack is to place this in your sources:
package org.springframework.boot.autoconfigure.web;
public interface ErrorController {
default String getErrorPath() { return "/error"; }
}
This will override the interface supplied by Spring.
We definitely discourage using Spring Cloud Zuul. The project is no longer maintained and there might be dependencies with vulnerabilities present. We encourage migrating to Spring Cloud Gateway instead.
@OlgaMaciaszek Is there any reference document for to migrate Zuul to Gateway? If it's straight forward then we can easily move else to upgrade the bunch of huge services is going to take some time.
@kurbhatt - it is quite straightforward. The main difference is that you will need to define the routes. There's no specific migration guide, but everything you'll need is in the Gateway documentation.
@OlgaMaciaszek I think migration to Spring cloud gateway is unfeasible in our case. The reason is that our api-gateway contains several controllers and also uses third-party libraries that are also dependant on spring-mvc. This is a problem since Spring cloud gateway is build on top of reactive stack (spring-webflux) and those two can not coexist in single application as far as I understand. Is my reasoning correct or I am missing something?
@LukeLaz You are correct. You will have to rewrite all the code that's incompatible with webflux. Worse, if you are forced to use 3rd party closed source code then there is no migration path.
It's very unfortunate it was decided that WebFlux should not coexist with MVC/Servlet API.
I found very simple and clean solution that can be used as long as your app does not use ErrorController
. Simply exclude ErrorMvcAutoConfiguration.class
from your app. ErrorController
won't be created so you will never get to the problematic part of if
in ZuulHandlerMapping
. In my case it was just adding it to already present exclusion list like this:
Before
@SpringBootApplication(exclude = {OAuth2ClientAutoConfiguration.class, LoggingAutoConfiguration.class})
After
@SpringBootApplication(exclude = {OAuth2ClientAutoConfiguration.class, LoggingAutoConfiguration.class, ErrorMvcAutoConfiguration.class})
After upgrade to Spring Boot 2.5.2 Zuul started to generate the following error:
With Boot 2.4.8 works fine.
This is my dependency in pom.xml.
Don't know for sure if I'm posting this in the correct project. If don't, please, point me in the right direction.
Thanks.
Complete stack trace: