@EnableZuulProxy doesn't work under a servlet 2.5 container. Is there any workaround to get spring-cloud zuul work under a servet 2.5 container?
Also I could not find the annotation processor of @EnableZuulProxy. Please provide the class which propesses @EnableZuulProxy so that I can better understand what this annotation really does.
Spring Cloud is meant to be run on servlet 3.0. That being said, it is possible to get @EnableZuulProxy running on servlet 2.5. I had to figure out a hack for this as I had to get this working in Tomcat 6.
The main issue is due to the ZuulConfiguration.class, which has the method:
@Bean
@ConditionalOnMissingBean(name = "zuulServlet")
public ServletRegistrationBean zuulServlet() { ... }
The issue here is that ServletRegistrationBean
uses javax.servlet.Registration$Dynamic
, which is not available until Servlet 3.0. This results in a NoClassDefFoundError
.
To work around this, use the spring-boot-legacy project to first register a DispatcherServlet. Secondly, you'll have to manually create a zuul servlet.
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.dm.gateway.microservicegateway.Application</param-value>
</context-param>
<listener>
<listener-class>org.springframework.boot.legacy.context.web.SpringBootContextLoaderListener</listener-class>
</listener>
<filter>
<filter-name>ContextLifecycleFilter</filter-name>
<filter-class>com.netflix.zuul.context.ContextLifecycleFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ContextLifecycleFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextAttribute</param-name>
<param-value>org.springframework.web.context.WebApplicationContext.ROOT</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>zuul</servlet-name>
<servlet-class>com.netflix.zuul.http.ZuulServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
I found the best way to remove the auto servlet registration, is to just make a verbatim copy of ZuulConfig
called ZuulOverrideConfig
, and remove the zuulServlet()
method. This is because the ZuulProxyConfiguration
extends ZuulConfiguration
, and it seemed to create the bean even when i tried to override it. I'm not 100% on the mechanics behind this, so there may be a better way.
The second change I made in ZuulOverrideConfig
was to call an extended implementation of ZuulFilterInitializer
, called 'LegacyZuulFilterInitializer`. This is because for some reason, the Zuul servlet was being crated, and able to be invoked, but no filters were bootstrapped. This extension is a hacky way to get the filters to bootstrap.
Next, I created a copy of ZuulProxyConfiguration
called ZuulLegacyProxyConfiguraiton
, and had it extend ZuulOverrideConfig.class
.
Finally, I annotated the Application class as follows.
@EnableCircuitBreaker
@EnableDiscoveryClient
@Import(ZuulLegacyProxyConfiguration.class)
@SpringBootApplication
public class Application {....}
After all these hacks, the implementation finally worked as expected. I wouldn't suggest using this for long, as it's pretty hacky. You won't get configuration class updates automatically when moving to new versions, and I can't guarantee that something won't break randomly!
This is using Spring Cloud 1.1.4.RELEASE