Could not find the FeatureManager - Minimal example for Togglz

2,113 views
Skip to first unread message

Florian Lüdiger

unread,
Jun 2, 2016, 9:26:23 AM6/2/16
to togglz-users
Hello there,

I am currently having a look at Togglz and wanted to create a quick minimal example application to see what Togglz is capable of.

I am just trying to implement a little java webapp which gets deployed to Apache Tomcat. No Spring Boot, CDI, JSF, ...

However, I always get the following error 
java.lang.IllegalStateException: Could not find the FeatureManager. For web applications please verify that the TogglzFilter starts up correctly.

I have already read this thread, so I guess, I do not have to implement my own FeatureManager but use the default FeatureManager provided by Togglz. I have no idea why Togglz does not find the default FeatureManager in my case.

I have attached my whole project, but at the bottom of my post are the most important parts.

Regards
Florian

web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

   
<context-param>
       
<param-name>org.togglz.core.manager.TogglzConfig</param-name>
       
<param-value>de.florianluediger.examples.togglz.DemoConfiguration</param-value>
   
</context-param>
</web-app>

pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   
<modelVersion>4.0.0</modelVersion>

   
<groupId>de.florianluediger.examples.togglz</groupId>
   
<artifactId>TogglzExample</artifactId>
   
<version>1.0-SNAPSHOT</version>

   
<dependencies>
       
<!-- Togglz core module (mandatory) -->
        <dependency>
           
<groupId>org.togglz</groupId>
           
<artifactId>togglz-core</artifactId>
           
<version>2.3.0.RC1</version>
       
</dependency>

       
<!-- Togglz for Servlet environments (mandatory) -->
        <dependency>
           
<groupId>org.togglz</groupId>
           
<artifactId>togglz-servlet</artifactId>
           
<version>2.3.0.RC1</version>
       
</dependency>

       
<!-- Togglz Admin Console -->
        <dependency>
           
<groupId>org.togglz</groupId>
           
<artifactId>togglz-console</artifactId>
           
<version>2.3.0.RC1</version>
       
</dependency>
   
</dependencies>
</project>

index.jsp:
<%@ page import="de.florianluediger.examples.togglz.MyFeatures" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
 
<head>
   
<title>Togglz example application</title>
 
</head>
 
<body>
   
<h1>Hello World</h1>
   
<%
        if (MyFeatures.FEATURE_ONE.isActive()) {
    %>
        <h2>Feature is active</h2>
   
<%
        }
    %>


  </body>
</html>

MyFeatures.java:
package de.florianluediger.examples.togglz;

import org.togglz.core.Feature;
import org.togglz.core.annotation.EnabledByDefault;
import org.togglz.core.annotation.Label;
import org.togglz.core.context.FeatureContext;

public enum MyFeatures implements Feature {
   
@EnabledByDefault
    @Label("First Feature")
   
FEATURE_ONE,

   
@Label("Second Feature")
   
FEATURE_TWO;

   
public boolean isActive() {
       
return FeatureContext.getFeatureManager().isActive(this);
   
}
}

DemoConfiguration.java:
package de.florianluediger.examples.togglz;

import org.togglz.core.Feature;
import org.togglz.core.manager.TogglzConfig;
import org.togglz.core.repository.StateRepository;
import org.togglz.core.repository.file.FileBasedStateRepository;
import org.togglz.core.user.UserProvider;
import org.togglz.servlet.user.ServletUserProvider;

import java.io.File;

//@ApplicationScoped
public class DemoConfiguration implements TogglzConfig {
   
public Class<? extends Feature> getFeatureClass() {
       
return MyFeatures.class;
   
}

   
public StateRepository getStateRepository() {
       
return new FileBasedStateRepository(new File("/tmp/features.properties"));
   
}

   
public UserProvider getUserProvider() {
       
return new ServletUserProvider("admin");
   
}
}

Florian Lüdiger

unread,
Jun 2, 2016, 9:29:23 AM6/2/16
to togglz-users
And the full Tomcat error
 

HTTP Status 500 - An exception occurred processing JSP page /de/florianluediger/examples/togglz/index.jsp at line 10

type Exception report

message An exception occurred processing JSP page /de/florianluediger/examples/togglz/index.jsp at line 10

description The server encountered an internal error that prevented it from fulfilling this request.

exception

org.apache.jasper.JasperException: An exception occurred processing JSP page /de/florianluediger/examples/togglz/index.jsp at line 10

7:   <body>
8:     <h1>Hello World</h1>
9:     <%
10:         if (MyFeatures.FEATURE_ONE.isActive()) {
11:     %>
12:         <h2>Feature is active</h2>
13:     <%


Stacktrace:
	org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:583)
	org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:476)
	org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:385)
	org.apache.jasper.servlet.JspServlet.service(JspServlet.java:329)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
	org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)

root cause

java.lang.IllegalStateException: Could not find the FeatureManager. For web applications please verify that the TogglzFilter starts up correctly. In other deployment scenarios you will typically have to implement a FeatureManagerProvider as described in the 'Advanced Configuration' chapter of the documentation.
	org.togglz.core.context.FeatureContext.getFeatureManager(FeatureContext.java:49)
	de.florianluediger.examples.togglz.MyFeatures.isActive(MyFeatures.java:17)
	org.apache.jsp.de.florianluediger.examples.togglz.index_jsp._jspService(index_jsp.java:121)
	org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
	org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:443)
	org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:385)
	org.apache.jasper.servlet.JspServlet.service(JspServlet.java:329)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
	org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)

note The full stack trace of the root cause is available in the Apache Tomcat/9.0.0.M6 logs.


Apache Tomcat/9.0.0.M6

Christian Kaltepoth

unread,
Jun 2, 2016, 11:43:47 AM6/2/16
to togglz...@googlegroups.com
Hi,

do you see any log entries from "TogglzFilter" in your log file? Looks like for some reason the filter doesn't start up correctly.

If the automatic registration of the filter doesn't work, you could also register the filter manually by adding this to your own web.xml:


Hope this helps

Christian

Florian Lüdiger

unread,
Jun 2, 2016, 12:12:41 PM6/2/16
to togglz-users
Hi Christian,

you mean in the tomcat logs? There are no entries containing the String "TogglzFilter".

Including the lines from your link to my web.xml file works and my application seems to work properly now.

If this is a bug and you want to fix it, I can provide you with further information (that I forgot in my original post):
- As you can see, the "@ApplicationScoped" line in the DemoConfiguration class is commented, because for some reason that annotation can not be found.
- I had to add all the togglz jar files to the tomcat.util.scan.StandardJarScanFilter.jarsToSkip in the catalina.properties file to skip tomcats TLD-scan (which failed for these jars).


I have another problem:
To my understanding, the admin console in my example should be located at http://localhost:8080/de/florianluediger/examples/togglz/togglz/
At this link, tomcat just throws a 404, do I have to enable the admin console somwhere explicitly? I use tomcat version 9.0.0, so Servlet 3.0 should not be an issue here.

Best regards
Florian

Christian Kaltepoth

unread,
Jun 3, 2016, 1:03:54 AM6/3/16
to togglz...@googlegroups.com
Hey Florian,

So it looks like the automatic registration of the filter failed for you. That's really weird. Removing @ApplicationScoped is fine if you don't use CDI. Why did you add all Togglz JARs to "jarsToSkip"? Maybe that is causing the issue? Could tell me more about the error you got? You wrote that you are using Tomcat 9? So you are using one of the latest milestones?

Regarding setting up the Togglz Admin Console. If the automatic registration of the filter failed, you will probably also have to register the required Servlet manually in your web.xml:


Hope this helps

Christian

Florian Lüdiger

unread,
Jun 3, 2016, 5:53:56 AM6/3/16
to togglz-users
Hi Christian,

First of all: I have tried to deploy my app without the filter and filter-mapping directions in the web.xml (which I added after reading your first post) and now it somehow works fine without, even though adding this fixed the issue for me in the first place. I have even installed a completely fresh version of Tomcat and it still works. However the admin console still does not work.

I have tried to use Tomcat 8 now, but that behaves just the same as Tomcat 9.

I have added the Togglz JARs to "jarsToSkip" because at some point, the deploying of my app did not work and it gave me the error:
org.apache.jasper.servlet.TldScanner.scanJars At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.

I have enabled debug logging and got the following output:
03-Jun-2016 11:43:19.539 FINE [RMI TCP Connection(3)-127.0.0.1] org.apache.jasper.servlet.TldScanner.scanResourcePaths No TLD files were found in resource path [/WEB-INF/].
03-Jun-2016 11:43:19.540 FINE [RMI TCP Connection(3)-127.0.0.1] org.apache.jasper.servlet.TldScanner$TldScannerCallback.scan No TLD files were found in [file:/C:/XXX/TogglzExample/out/artifacts/TogglzExample_war_exploded/WEB-INF/lib/togglz-servlet-2.3.0.RC1.jar]. Consider adding the JAR to the tomcat.util.scan.StandardJarScanFilter.jarsToSkip property in CATALINA_BASE/conf/catalina.properties file.
03-Jun-2016 11:43:19.541 FINE [RMI TCP Connection(3)-127.0.0.1] org.apache.jasper.servlet.TldScanner$TldScannerCallback.scan No TLD files were found in [file:/C:/XXX/TogglzExample/out/artifacts/TogglzExample_war_exploded/WEB-INF/lib/togglz-core-2.3.0.RC1.jar]. Consider adding the JAR to the tomcat.util.scan.StandardJarScanFilter.jarsToSkip property in CATALINA_BASE/conf/catalina.properties file.
03-Jun-2016 11:43:19.542 FINE [RMI TCP Connection(3)-127.0.0.1] org.apache.jasper.servlet.TldScanner$TldScannerCallback.scan No TLD files were found in [file:/C:/XXX/TogglzExample/out/artifacts/TogglzExample_war_exploded/WEB-INF/lib/togglz-console-2.3.0.RC1.jar]. Consider adding the JAR to the tomcat.util.scan.StandardJarScanFilter.jarsToSkip property in CATALINA_BASE/conf/catalina.properties file.

Adding these files to "jarsToSkip" did not actually fix my deployment problem back then. Now removing the entry from "jarsToSkip" has no effect on the deployment, everything seems to work fine.
However removing the JARs from "jarsToSkip" does not fix the issue that my admin console is not working.


Adding the code from your link to my web.xml has no effect. The admin console still is not reacheable under http://localhost:8080/de/florianluediger/examples/tgz/togglz (i have renamed the package "togglz" to "tgz").
I don't even get any error at the Tomcat console output.

Thanks for the great help
Florian

Christian Kaltepoth

unread,
Jun 3, 2016, 6:05:33 AM6/3/16
to togglz...@googlegroups.com
Hi Florian,

please make sure that the UserProvider which you configured in your TogglzConfig returns a user which has permissions to access the console. In the configuration you posted in your first mail you are using the ServletUserProvider which the admin role set to "admin". This means that only users authenticated against Tomcat having the role "admin" will be able to use the console.

As a quick text you can replace the UserProvider configuration with this:

    @Override
    public UserProvider getUserProvider() {
        return new UserProvider() {
            @Override
            public FeatureUser getCurrentUser() {
                return new SimpleFeatureUser("admin", true);
            }
        };
    }

BTW: Are you getting a 404 or some other response code?

Christian

Florian Lüdiger

unread,
Jun 3, 2016, 6:33:28 AM6/3/16
to togglz-users
Hi Christian,

I guessed, that I would get problems because of that, but I expected a permission denied error or something like that.
However, adding that code still gives me a 404 when trying to access the admin console.
I was getting a 404 before and still get the same error.
Maybe, I am looking at the wrong URL?

Best regards
Florian

Christian Kaltepoth

unread,
Jun 3, 2016, 7:21:51 AM6/3/16
to togglz...@googlegroups.com
Could you share your configuration?
Message has been deleted
Message has been deleted
Message has been deleted
Message has been deleted

Florian Lüdiger

unread,
Jun 3, 2016, 8:44:40 AM6/3/16
to togglz-users
Hello Christian,

I am not sure which configuration you mean, so attached you can find the whole tomcat configuration folder.

Best regards
Florian
tomcat_conf.zip
Message has been deleted

Christian Kaltepoth

unread,
Jun 3, 2016, 9:03:03 AM6/3/16
to togglz...@googlegroups.com
I was referring to your TogglzConfig and web.xml... ;)

Florian Lüdiger

unread,
Jun 3, 2016, 9:09:52 AM6/3/16
to togglz-users
Hi Christian,

here you go

TogglzConfig:
package de.florianluediger.examples.tgz;


import org.togglz.core.Feature;
import org.togglz.core.manager.TogglzConfig;
import org.togglz.core.repository.StateRepository;
import org.togglz.core.repository.file.FileBasedStateRepository;
import org.togglz.core.user.FeatureUser;
import org.togglz.core.user.SimpleFeatureUser;
import org.togglz.core.user.UserProvider;

import java.io.File;


public class DemoConfiguration implements TogglzConfig {
   
public Class<? extends Feature> getFeatureClass() {
       
return MyFeatures.class;
   
}

   
public StateRepository getStateRepository() {
       
return new FileBasedStateRepository(new File("/tmp/features.properties"));
   
}


   
public UserProvider getUserProvider() {
       
return new UserProvider() {

           
public FeatureUser getCurrentUser() {
               
return new SimpleFeatureUser("admin", true);
           
}
       
};
   
}
}

web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

   
<context-param>
       
<param-name>org.togglz.core.manager.TogglzConfig</param-name>

       
<param-value>de.florianluediger.examples.tgz.DemoConfiguration</param-value>
   
</context-param>

   
<!--<filter>
        <filter-name>TogglzFilter</filter-name>
        <filter-class>org.tgz.servlet.TogglzFilter</filter-class>
        <async-supported>true</async-supported>
    </filter>
    <filter-mapping>
        <filter-name>TogglzFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>-->

   
</web-app>


Christian Kaltepoth

unread,
Jun 3, 2016, 9:22:19 AM6/3/16
to togglz...@googlegroups.com
In this case you should see the console if you access:



Florian Lüdiger

unread,
Jun 3, 2016, 9:35:08 AM6/3/16
to togglz-users
Okay, it works now. I have totally misunderstood the "context path" phrase.
In my example, I can access the admin console at http://localhost:8080/togglz/

Thanks again for all the help and have a nice weekend
Florian

Christian Kaltepoth

unread,
Jun 3, 2016, 9:42:31 AM6/3/16
to togglz...@googlegroups.com
You're welcome! :)
Reply all
Reply to author
Forward
0 new messages