Spring Cloud Netflix provides easy way of routing using Zuul proxy. It has a feature of circuit breaker in case of heavy load. Though underlying Hystrix provides a fallback, till recently Zuul didn't provide same. Zuul implemented this functionality in Camden SR2. Documentation for using Zuul Fallback is available here.
If you have multiple Zuul routes in your application, it will be cumbersome to write multiple fallback providers. GenericZuulFallbackProvider.java below can be used to provide a generic fallback in your application. Then you need to provide a bean for each route returning this generic fallback after setting route (and other fields like status code, response body etc). Example of beans are available below in ZuulProxyApplication.java.
There is pending enhancement to provide default Zuul fallback. Below code might be still useful for cases where you need to override only some fields.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## Part of application.yml | |
zuul: | |
routes: | |
route1: | |
path: /route1/** | |
strip-prefix: false | |
route2: | |
path: /route2/** | |
strip-prefix: false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.Zullfallback; | |
import java.io.ByteArrayInputStream; | |
import java.io.IOException; | |
import java.io.InputStream; | |
import org.springframework.cloud.netflix.zuul.filters.route.ZuulFallbackProvider; | |
import org.springframework.http.HttpHeaders; | |
import org.springframework.http.HttpStatus; | |
import org.springframework.http.MediaType; | |
import org.springframework.http.client.ClientHttpResponse; | |
public class GenericZuulFallbackProvider implements ZuulFallbackProvider { | |
private String responseBody = "{\"message\":\"Service Unavailable. Please try after sometime\"}"; | |
private HttpHeaders headers = null; | |
private String route = null; | |
private int rawStatusCode = 503; | |
private HttpStatus statusCode = HttpStatus.SERVICE_UNAVAILABLE; | |
private String statusText = "Service Unavailable"; | |
public String getStatusText() { | |
return statusText; | |
} | |
public void setStatusText(String statusText) { | |
this.statusText = statusText; | |
} | |
public HttpHeaders getHeaders() { | |
return headers; | |
} | |
public int getRawStatusCode() { | |
return rawStatusCode; | |
} | |
public HttpStatus getStatusCode() { | |
return statusCode; | |
} | |
public void setRawStatusCode(int rawStatusCode) { | |
this.rawStatusCode = rawStatusCode; | |
} | |
public void setStatusCode(HttpStatus statusCode) { | |
this.statusCode = statusCode; | |
} | |
public void setHeaders(HttpHeaders headers) { | |
this.headers = headers; | |
} | |
public void setRoute(String route) { | |
this.route = route; | |
} | |
public String getResponseBody() { | |
return responseBody; | |
} | |
public void setResponseBody(String responseBody) { | |
this.responseBody = responseBody; | |
} | |
@Override | |
public ClientHttpResponse fallbackResponse() { | |
return new ClientHttpResponse(){ | |
@Override | |
public InputStream getBody() throws IOException { | |
if (responseBody == null) | |
responseBody ="{\"message\":\"Service Unavailable. Please try after sometime\"}"; | |
return new ByteArrayInputStream(responseBody.getBytes()); | |
} | |
@Override | |
public HttpHeaders getHeaders() { | |
if (headers == null) { | |
headers = new HttpHeaders(); | |
headers.setContentType(MediaType.APPLICATION_JSON); | |
} | |
return headers; | |
} | |
@Override | |
public void close() { | |
} | |
@Override | |
public int getRawStatusCode() throws IOException { | |
return rawStatusCode; | |
} | |
@Override | |
public HttpStatus getStatusCode() throws IOException { | |
if (statusCode == null) | |
statusCode = HttpStatus.SERVICE_UNAVAILABLE; | |
return statusCode; | |
} | |
@Override | |
public String getStatusText() throws IOException { | |
if (statusText == null) | |
statusText = "Service Unavailable"; | |
return statusText; | |
} | |
}; | |
} | |
@Override | |
public String getRoute() { | |
if (route == null) | |
route = "route"; | |
return route; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.ZuulProxy; | |
import java.io.File; | |
import org.springframework.beans.factory.annotation.Value; | |
import org.springframework.boot.autoconfigure.SpringBootApplication; | |
import org.springframework.boot.builder.SpringApplicationBuilder; | |
import org.springframework.cloud.netflix.zuul.EnableZuulProxy; | |
import org.springframework.context.annotation.Bean; | |
import org.springframework.stereotype.Controller; | |
import com.example.Zullfallback; | |
import org.springframework.cloud.netflix.zuul.filters.route.ZuulFallbackProvider; | |
@SpringBootApplication | |
@Controller | |
@EnableZuulProxy | |
public class ZuulProxyApplication { | |
public static void main(String[] args) { | |
new SpringApplicationBuilder(ZuulProxyApplication.class).web(true).run(args); | |
} | |
@Bean | |
public ZuulFallbackProvider route1ZuulFallbackProvider() { | |
GenericZuulFallbackProvider route1ZuulFallback = new GenericZuulFallbackProvider(); | |
route1ZuulFallback.setRoute("route1"); | |
return route1ZuulFallback; | |
} | |
@Bean | |
public ZuulFallbackProvider route2ZuulFallbackProvider() { | |
GenericZuulFallbackProvider route2ZullFallback = new GenericZuulFallbackProvider(); | |
route2ZullFallback.setRoute("route2"); | |
route2ZuulFallback.setRawStatusCode(200); | |
route2ZuulFallback.setStatusCode(HttpStatus.OK); | |
route2ZuulFallback.setResponseBody("We are little busy. Comeback After Sometime"); | |
return portalZullFallback; | |
} | |
} |