Working with the template engine

We are enabling and disabling the fibonacci feature, but there are many other cases where the Feature Toggle can be very useful. One of them is hiding a web link that links to an unfinished feature. This is an interesting use because we can test what we released to production using its URL, but it will be hidden for the rest of the users for as long as we want.

To illustrate this behavior, we are going to create a simple web page using the already mentioned Thymeleaf framework.

First of all, we add a new control flag:

features: 
    fibonacci: 
        restEnabled: true 
        webEnabled: true 

Next, map this new flag in a configuration class:

    private boolean webEnabled; 
    public boolean isWebEnabled() { 
        return webEnabled; 
    } 
 
    public void setWebEnabled(boolean webEnabled) { 
        this.webEnabled = webEnabled; 
    } 

We are going to create two templates. The first one is the home page. It contains some links to different Fibonacci number computations. These links should be visible only when the feature is enabled, so there's an optional block to simulate this behavior:

<!DOCTYPE html> 
<html xmlns:th="http://www.thymeleaf.org"> 
<head lang="en"> 
    <meta http-equiv="Content-Type" 
          content="text/html; charset=UTF-8" /> 
    <title>HOME - Fibonacci</title> 
</head> 
<body> 
<div th:if="${isWebEnabled}"> 
    <p>List of links:</p> 
    <ul th:each="number : ${arrayOfInts}"> 
        <li><a 
            th:href="@{/web/fibonacci(number=${number})}" 
            th:text="'Compute ' + ${number} + 'th fibonacci'"> 
        </a></li> 
    </ul> 
</div> 
</body> 
</html> 

The second one just shows the value of the computed Fibonacci number and also a link to go back to the home page:

<!DOCTYPE html> 
<html xmlns:th="http://www.thymeleaf.org"> 
<head lang="en"> 
    <meta http-equiv="Content-Type" 
          content="text/html; charset=UTF-8" /> 
    <title>Fibonacci Example</title> 
</head> 
<body> 
<p th:text="${number} + 'th number: ' + ${value}"></p> 
<a th:href="@{/}">back</a> 
</body> 
</html> 

In order to get both templates to work, they should be in a specific location. They are src/main/resources/templates/home.html and src/main/resources/templates/fibonacci.html respectively.

Finally, the masterpiece, which is the controller that connects all this and makes it work:

@Controller 
public class FibonacciWebController { 
    @Autowired 
    FibonacciFeatureConfig fibonacciFeatureConfig; 
 
    @Autowired 
    @Qualifier("fibonacci") 
    private FibonacciService fibonacciProvider; 
 
    @RequestMapping(value = "/", method = GET) 
    public String home(Model model) { 
        model.addAttribute( 
            "isWebEnabled", 
            fibonacciFeatureConfig.isWebEnabled() 
        ); 
        if (fibonacciFeatureConfig.isWebEnabled()) { 
            model.addAttribute( 
                "arrayOfInts", 
                Arrays.asList(5, 7, 8, 16) 
            ); 
        } 
        return "home"; 
    } 
 
    @RequestMapping(value ="/web/fibonacci", method = GET) 
    public String fibonacci( 
            @RequestParam(value = "number") Integer number, 
            Model model) { 
        if (number != null) { 
            model.addAttribute("number", number); 
            model.addAttribute( 
                "value", 
                fibonacciProvider.getNthNumber(number)); 
        } 
        return "fibonacci"; 
    } 
} 

Note that this controller and the previous one seen in the REST API example share some similarities. This is because both are constructed with the same framework and use the same resources. However, there are slight differences between them; one is annotated as @Controller instead of both being @RestController. This is because the web controller is serving template pages with custom information, while the REST API generates a JSON object response.

Let's see this working, again using this Gradle command:

    $> gradle clean run
  

This is the generated home page:

This is shown when visiting the Fibonacci number link:

But we turn off the feature using the following code:

features: 
    fibonacci: 
        restEnabled: true 
        webEnabled: false 

Relaunching the application, we browse to the home page and see that those links are not shown anymore, but we can still access the page if we already know the URL. If we manually write http://localhost:8080/web/fibonacci?number=15, we can still access the page:

This practice is very useful, but it usually adds unnecessary complexity to your code. Don't forget to refactor the code, deleting old toggles that you won't use anymore. It will keep your code clean and readable. Also, a good point is getting this working without restarting the application. There are many storage options that do not require a restart, databases being the most popular.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.133.123.34