Skip to content

Instantly share code, notes, and snippets.

@aldobongio
Created August 18, 2021 14:12
Show Gist options
  • Select an option

  • Save aldobongio/6a22f49863c7a777612f7887bbb8fd1d to your computer and use it in GitHub Desktop.

Select an option

Save aldobongio/6a22f49863c7a777612f7887bbb8fd1d to your computer and use it in GitHub Desktop.
Fix for Spring Boot 2.5.x + Zuul - NoSuchMethodError: ErrorController.getErrorPath()
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.CallbackFilter;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import org.springframework.cglib.proxy.NoOp;
import org.springframework.cloud.netflix.zuul.filters.RouteLocator;
import org.springframework.cloud.netflix.zuul.web.ZuulController;
import org.springframework.cloud.netflix.zuul.web.ZuulHandlerMapping;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/** Zuul configuration. */
@Configuration
public class ZuulConfiguration {
/** The path returned by ErrorContoller.getErrorPath() with Spring Boot < 2.5 (and no longer available on Spring Boot >= 2.5). */
private static final String ERROR_PATH = "/error";
/**
* Constructs a new bean post-processor for Zuul.
*
* @param routeLocator
* the route locator.
* @param zuulController
* the Zuul controller.
* @param errorController
* the error controller.
* @return the new bean post-processor.
*/
@Bean
public ZuulPostProcessor zuulPostProcessor(@Autowired RouteLocator routeLocator, @Autowired ZuulController zuulController,
@Autowired(required = false) ErrorController errorController) {
return new ZuulPostProcessor(routeLocator, zuulController, errorController);
}
private static final class ZuulPostProcessor implements BeanPostProcessor {
private final RouteLocator routeLocator;
private final ZuulController zuulController;
private final boolean hasErrorController;
ZuulPostProcessor(RouteLocator routeLocator, ZuulController zuulController, ErrorController errorController) {
this.routeLocator = routeLocator;
this.zuulController = zuulController;
this.hasErrorController = (errorController != null);
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (hasErrorController && (bean instanceof ZuulHandlerMapping)) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(ZuulHandlerMapping.class);
enhancer.setCallbackFilter(LookupHandlerCallbackFilter.INSTANCE); // only for lookupHandler
enhancer.setCallbacks(new Callback[] { LookupHandlerMethodInterceptor.INSTANCE, NoOp.INSTANCE });
Constructor<?> ctor = ZuulHandlerMapping.class.getConstructors()[0];
return enhancer.create(ctor.getParameterTypes(), new Object[] { routeLocator, zuulController });
}
return bean;
}
}
private static enum LookupHandlerCallbackFilter implements CallbackFilter {
INSTANCE;
@Override
public int accept(Method method) {
if ("lookupHandler".equals(method.getName())) {
return 0;
}
return 1;
}
}
private static enum LookupHandlerMethodInterceptor implements MethodInterceptor {
INSTANCE;
@Override
public Object intercept(Object target, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
if (ERROR_PATH.equals(args[0])) {
/* by entering this branch we avoid the ZuulHandlerMapping.lookupHandler method to trigger the NoSuchMethodError */
return null;
}
return methodProxy.invokeSuper(target, args);
}
}
}
@aldobongio
Copy link
Copy Markdown
Author

Relates to this issue

@varunshet393
Copy link
Copy Markdown

@aldobonigo How do i integrate same to my Zuul application ? just create the same class in configuration package and run the same ?

@julianoBRL
Copy link
Copy Markdown

julianoBRL commented Sep 16, 2021

@varunshet393

The last time i used this code in my project i just created it and started the application, it started with the application itself.

@sandipchitale
Copy link
Copy Markdown

Thanks!

@csh0711
Copy link
Copy Markdown

csh0711 commented Dec 28, 2021

Thanks a lot! :-)

@wilfridmaxis
Copy link
Copy Markdown

Thank you for this solution. I am using it and see that My Filter to inject the Authorization Header is not Invoked. Did you have the same problem?

@yassinemenssi
Copy link
Copy Markdown

Thanks!!

@waeng
Copy link
Copy Markdown

waeng commented Feb 26, 2022

Thanks!!

@free-leung
Copy link
Copy Markdown

Thanks a lot! It's working now.

@ronaimate
Copy link
Copy Markdown

Thanks!!!

@artwellmamvura
Copy link
Copy Markdown

This worked instantly with

org.springframework.boot - spring-boot-starter-parent - 2.6.4

Was getting http 500 error for the Eureka server

@mahulivishal
Copy link
Copy Markdown

Is this fix tested for 2.6.6 of spring-boot?

@frankyhollywood
Copy link
Copy Markdown

also works for upgrade to spring-boot 2.6.7, thx!

@and-ratajski
Copy link
Copy Markdown

Seems to work in ver. 2.7.1 as well! - At least this very error is gone ๐Ÿ˜‰ THANKS!

@rebel-codeaz
Copy link
Copy Markdown

Seems to work in ver. 2.7.1 as well! - At least this very error is gone wink THANKS!

Hey! I'm a newbie to learn microservices using spring boot. Can anybody tell where to create this file? I'm getting error in the pom.xml itself. Using spring version 2.7.5

@SAURABH384
Copy link
Copy Markdown

Hi I am trying to migrate a spring boot 2.4.4 and zuul 1.3.1 to 2.7.0 but its not working with 1.3.1 so I tried to upgarde to zuul 2.0.0 but now issue is In my Code RequestContext was used But now in zuul 2.0.0 Its not there Any Idea How to Fix it.

@mnavyasri
Copy link
Copy Markdown

does this solution is working with spring boot 3.0.5

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment