Togglz & Spring Boot: Could not find the FeatureManager

5,729 views
Skip to first unread message

Slava Semushin

unread,
May 8, 2015, 5:01:25 PM5/8/15
to togglz...@googlegroups.com
Hello,

does anyone know a proper way to bootstrap Toggz in Spring Boot? I run application via mvn spring-boot:run command and get the following error:

Caused by: 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.
at org.togglz.core.context.FeatureContext.getFeatureManager(FeatureContext.java:49)
at org.togglz.core.manager.LazyResolvingFeatureManager.getDelegate(LazyResolvingFeatureManager.java:24)
at org.togglz.core.manager.LazyResolvingFeatureManager.isActive(LazyResolvingFeatureManager.java:44)
at com.github.heneke.thymeleaf.togglz.processor.AbstractFeatureAttrProcessor.isFeatureActive(AbstractFeatureAttrProcessor.java:67)
at com.github.heneke.thymeleaf.togglz.processor.AbstractFeatureAttrProcessor.determineFeatureState(AbstractFeatureAttrProcessor.java:59)
at com.github.heneke.thymeleaf.togglz.processor.FeatureActiveAttrProcessor.isVisible(FeatureActiveAttrProcessor.java:65)
at org.thymeleaf.processor.attr.AbstractConditionalVisibilityAttrProcessor.processAttribute(AbstractConditionalVisibilityAttrProcessor.java:59)
at org.thymeleaf.processor.attr.AbstractAttrProcessor.doProcess(AbstractAttrProcessor.java:87)
at org.thymeleaf.processor.AbstractProcessor.process(AbstractProcessor.java:212)
... 88 common frames omitted

I've tried many different ways but no luck.

Thanks in advance!

Christian Kaltepoth

unread,
May 9, 2015, 5:40:53 AM5/9/15
to togglz...@googlegroups.com
Hi,

could you describe the way you used to configure Togglz. There are many different ways for this, so which one you are using would be interesting to see.

Christian

Slava Semushin

unread,
May 12, 2015, 4:29:47 AM5/12/15
to togglz...@googlegroups.com
Hello,

I've managed this issue by using StaticFeatureManagerProvider.

Example fix:

https://github.com/php-coder/mystamps/commit/dddae413c0a98a686dae744cfab2827998950728#diff-209597485b47d881c38c12eb6399c262R19


суббота, 9 мая 2015 г., 0:01:25 UTC+3 пользователь Slava Semushin написал:

Christian Kaltepoth

unread,
May 12, 2015, 4:38:29 AM5/12/15
to togglz...@googlegroups.com
Great. Yeah, I think using StaticFeatureManagerProvider is absolutely fine for Spring Boot.

Marcel Overdijk

unread,
Jan 12, 2016, 10:27:54 AM1/12/16
to togglz-users
I'm facing this now as well.

Do you really think using the StaticFeatureManagerProvider is the way forward here?
As it then also should be used for getting the FeatureManager instead of the FeatureContext.
It also uses static var so you might end up with problems when running 2 apps under same jvm process.

I have the togglz spring web integration module, and Spring Boot creates a bean of type FeatureManager.
Shouldn't this be enough?
I'm wondering if the SpringWebBeanFinder is kicking in, or maybe to late?

In the running app the featureManager bean exists but when trying to see if a feature is active I get the "Could not find the FeatureManager".
Should I explicitly add the Togglz filter? I read in installation that this should be done automatically in servlet 3.0 env.

Christian Kaltepoth

unread,
Jan 12, 2016, 10:44:17 AM1/12/16
to togglz...@googlegroups.com
First of all: FeatureContext basically just a facade which will effectively use StaticFeatureManagerProvider under the hood if you use this implementation.

Basically you should StaticFeatureManagerProvider use only in standalone apps. Because it uses static references.

If Spring definitively creates a FeatureManager, then SpringWebBeanFinder should find it. For some reason this seems to be problematic in Spring Boot environments!? I'm not sure why.

If you want good integration with Spring Boot, there should be an implementation of BeanFinder which is able to locate the ApplicationContext used by the Spring Boot app and lookup beans by their type from it.

Christian

Marcel Overdijk

unread,
Jan 12, 2016, 11:15:53 AM1/12/16
to togglz-users
OK these are some good pointers, I will look into it further.

Christian Kaltepoth

unread,
Jan 12, 2016, 11:24:10 AM1/12/16
to togglz...@googlegroups.com

Ok, great... Some debugging in SpringWebBeanFinder may help here...

Marcel Overdijk

unread,
Jan 12, 2016, 4:50:39 PM1/12/16
to togglz-users
Yes I noticed the SpringWebBeanFinder tries to find a bean of type TogglzBootstrap or TogglzConfig.
So only having a FeatureManager bean in the application context is not enough.

When I explicitly create a TogglzConfig then the app starts without problems.

Is there a reason why the BeanFinder does not look directly for FeatureManager?
When programatically configuring Togglz the FeatureManager (via FeatureManagerBuilder) seems the easiest approach.

Christian Kaltepoth

unread,
Jan 13, 2016, 12:50:01 AM1/13/16
to togglz...@googlegroups.com
I just added some architecture documentation to the wiki which hopefully explains how the bootstrapping process works:


Could you have a look at it? Togglz will basically just look for TogglzBootstrap/TogglzConfig if it doesn't find a FeatureManager via the BeanFinder SPI before. But perhaps you discovered a bug?

Christian


Christian Kaltepoth

unread,
Jan 13, 2016, 12:59:48 AM1/13/16
to togglz...@googlegroups.com
Two additional notes.

In your case it would make sense to use "Application managed FeatureManager" mode.

And perhaps increasing the logging level will reveal, which of the SPIs get called in which order.

Christian

Marcel Overdijk

unread,
Jan 13, 2016, 10:05:36 AM1/13/16
to togglz-users
Using the "Application managed FeatureManager" mode I think something like 

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

won't work anymore in a Features enum I assume.

The reason why SpringWebBeanFinder is not finding the FeatureManager bean is that it cannot get the ApplicationContext.

public class SpringWebBeanFinder implements BeanFinder {

@Override
public <T> Collection<T> find(Class<T> clazz, Object context) {

Collection<T> result = new ArrayList<T>();

// use the Spring API to obtain the WebApplicationContext
WebApplicationContext applicationContext = null;
if (context instanceof ServletContext) {
applicationContext = WebApplicationContextUtils.getWebApplicationContext((ServletContext) context);
}
if (applicationContext == null) {
applicationContext = ContextLoader.getCurrentWebApplicationContext();
}

The passed in context is always null in this scenario:

See 2nd argument in

Collection<FeatureManager> result = beanFinder.find(FeatureManager.class, null);

which is done in BeanFinderFeatureManagerProvider.

The 
applicationContext = ContextLoader.getCurrentWebApplicationContext();

won't work as Spring Boot doesn’t use ContextLoaderListener so ContextLoader will never be able to provide access to the current web application context.

Would it be possible to provide the ServletContext to SpringWebBeanFinder ?
In that case 

WebApplicationContextUtils.getWebApplicationContext((ServletContext) context);

will work!


Marcel

Christian Kaltepoth

unread,
Jan 13, 2016, 10:22:42 AM1/13/16
to togglz...@googlegroups.com
Thanks for the debugging. This could explain the issue Spring Boot users reported. 

Too bad ContextLoader.getCurrentWebApplicationContext() doesn't work here. It would be interesting to know what the preferred way of obtaining the ApplicationContext is in Spring Boot applications.

Unfortunately obtaining the ServletContext isn't very easy either. That's why I'm surprised that ContextLoader.getCurrentWebApplicationContext() doesn't work for Spring Boot. The MUST be some way to obtain the current ApplicationContext from somewhere. 

Anyone has any insights on this?

Marcel Overdijk

unread,
Jan 13, 2016, 10:41:06 AM1/13/16
to togglz-users
I spoke to the Boot guys and they suggested using the servlet context to retrieve it....

Of course I can always create a TogglzConfig bean instead of a FeatureManager then it should work.
But FeatureManager does sound the more appropriate for this.

Marcel Overdijk

unread,
Jan 13, 2016, 4:53:37 PM1/13/16
to togglz-users
Why can't the FeatureManagerBootstrapper simply also lookup a bean of type FeatureManager?
It does already do a lookup for TooglzBootstrap and TogglzConfig...
The lookup already used the SPI bean finders so everything is in place to work. What do you think?

Christian Kaltepoth

unread,
Jan 14, 2016, 4:06:33 AM1/14/16
to togglz...@googlegroups.com
Not sure I like the idea for the following reasons:
  • The purpose of FeatureManagerBootstrapper is to *create* a FeatureManager, not to look it up
  • This would result in Togglz trying to manage the life cycle of the FeatureManager, although it is actually managed by Spring Boot
  • The FeatureManagerProvider SPI will possibly be called later on, which then will probably fail
Please also note that the "Application managed FeatureManager" is actually now the preferred way of using Togglz. Actually I was thinking about deprecating TogglzConfig, TogglzBootstrap, FeatureManagerBootstrapper in Togglz 3.0.

However, in the meantime I found a way which could fix this issue. I just committed a patch to the SpringWebBeanFinder.


Could you give the latest snapshots a try?

Christian

Marcel Overdijk

unread,
Jan 14, 2016, 7:19:53 AM1/14/16
to togglz-users
Hi,

I you are thinking about deprecating TogglzBootstrap, TogglzBootstrap and FeatureManagerBootstrapper I think it's wise to use the "Application managed FeatureManager" mode anyway.
This alo suits better in DI-like environments.

I was already experimenting with this.
In that case I didn't use the TogglzBootstrap/Config and also removed the TogglzFilter.
In that case the admin servlet did not work anymore (makes sense), but because of this fix in the latest snapshot this might be resolved then; I will have a look.

Marcel Overdijk

unread,
Jan 14, 2016, 7:30:54 AM1/14/16
to togglz-users
PS: are the snapshots deployed somewhere accessable by Maven?

Marcel Overdijk

unread,
Jan 14, 2016, 8:07:58 AM1/14/16
to togglz-users
I think the fix makes no difference.

public class BeanFinderFeatureManagerProvider implements FeatureManagerProvider {

@Override
public int priority() {
return 60;
}

@Override
public FeatureManager getFeatureManager() {

// we _may_ find multiple managers, which will lead to an error
Set<FeatureManager> managers = new HashSet<FeatureManager>();

// ask all providers for managed FeatureManager
for (BeanFinder beanFinder : ServiceLoader.load(BeanFinder.class)) {

Collection<FeatureManager> result = beanFinder.find(FeatureManager.class, null);
            if (result != null) {
managers.addAll(result);
}
}

I still need a TogglzBootstrap or TogglzConfig as the BeanFinderFeatureManagerProvider still lookups a FeatureManager without passing in the context.
And then the TogglzFilter will fail as it can't find the TogglzBootstrap/Config.

I was also looking in using the "Application managed FeatureManager" mode which works in my application.
However how would the admin console servlet get a hold to the feature manager in this case?
If I remove the the filter (which does not work without TogglzBootstrap/Config anyway it seems) as soon as I go to /togglz the feature manager cannot be found.
It tries to find the bean via SpringWebBeanFinder but also in this case the context is null and hence the application context cannot be found.
Maybe the this can be passed from console servlet to the bean finder?

Christian Kaltepoth

unread,
Jan 14, 2016, 8:48:28 AM1/14/16
to togglz...@googlegroups.com
So the error occurs during startup, correct?

Could you try adding this to your web.xml?

  <context-param>
    <param-name>org.togglz.FEATURE_MANAGER_PROVIDED</param-name>
    <param-value>true</param-value>
  </context-param>

However, for a really solid integration with Spring Boot, there has to be a BeanFinder implementation which is able able to resolve beans without the ServletContext being provided. There are definitely situations for which the caller cannot provide the ServletContext. And even providing it in "more but not all situations" would require to modify interfaces which will lead to a breaking API change.

What I think is required is a SpringBootBeanFinder. You could for example observe the startup of Spring Boot (I guess there is an API for that) and then store the ApplicationContext in a map for each context class loader. It is safe to do so because each web application gets its own context class loader. This is basically what Spring's ContextLoader also does. Storing some object for each context class loader isn't that difficult. Have a look at this class which does something like that:


So you will need something similar. You will just have to store the ApplicationContext instead. Then you can implement the SpringBootBeanFinder which would lookup the ApplicationContext by the currently context class loader and then lookup the requested bean.

Christian



Marcel Overdijk

unread,
Jan 14, 2016, 9:59:35 AM1/14/16
to togglz-users
Hi Christian,

I will look into it but after speaking to Boot guys there is no easy - non-hackish - wat to get the application context.
From their point of view Togglz is not DI-friendly enough.

Christian Kaltepoth

unread,
Jan 14, 2016, 10:08:41 AM1/14/16
to togglz...@googlegroups.com
The problem is that Togglz tries to support all large range of environments. It has to work with Spring, CDI, Guice or even without any DI container. That's not so easy to accomplish. :)

Most environments allow some way to lookup the DI container. CDI for example allows to call CDI.current() to get it. And event Spring supports it with ContextLoader.getCurrentWebApplicationContext().

By the way. Even Spring's ContextLoader uses the same approach I suggested, which is storing the ApplicationContext in a map using the context classloader:


So I don't think it is very hackish. ;)

Christian

Marcel Overdijk

unread,
Jan 14, 2016, 10:31:38 AM1/14/16
to togglz-users
I think I found a way.

In the application itself I think it's good to use the Application managed FeatureManager" mode.
That being said we don't need TogglzBootstrap, TogglzConfig and also not the TogglzConfig.
Checking if a feature is active can be done directly using the FeatureManager like: featureManager.isActive(MyFeatures.HELLO_WORLD)

Now the only problem left is than the Admin Console.
I created a custom SpringBootFeatureManagerProvider which uses Spring's RequestContextHolder to get the servlet context.
With that I can get the ApplicationContext using the WebApplicationContextUtils.
This all seems to work :-)


Christian Kaltepoth

unread,
Jan 14, 2016, 10:37:32 AM1/14/16
to togglz...@googlegroups.com
Sounds great. :)

But even FeatureContext.getFeatureManager() should work in this setup. At least if you added:

  <context-param>
    <param-name>org.togglz.FEATURE_MANAGER_PROVIDED</param-name>
    <param-value>true</param-value>
  </context-param>

Christian

Marcel Overdijk

unread,
Jan 14, 2016, 11:27:05 AM1/14/16
to togglz-users
OK will try that later today.

Marcel Overdijk

unread,
Jan 14, 2016, 3:11:59 PM1/14/16
to togglz-users
The way I implemented it using the custom SpringBootFeatureManagerProvider which uses Spring's RequestContextHolder will only work when in a web request.
So using FeatureContext in the enum is not completely safe. E.g. if you want to use it during startup of the application it won't have the RequestContextHolder set.
I think in this case it's better to use the Feature Manager then directly.

The only reason for the SpringBootFeatureManagerProvider atm is the Admin Console so far.
When using the Admin Console we will always have a request.

Do yo maybe foresee problems?

Christian Kaltepoth

unread,
Jan 15, 2016, 1:16:44 AM1/15/16
to togglz...@googlegroups.com
I still think that having a SpringBootBeanFinder would be great. Especially because with this in place everything should simply work without any drawbacks. That's because all other integrations (plain Spring, CDI, Guice) work the same way.

Is there any way to observe the Spring Boot startup and shutdown? Some kind of callback which is executed when Spring Boot starts and stops and provides access to the ApplicationContext? If so, could you perhaps prepare the corresponding code in your sample app. Having this in place I think I can add such a SpringBootBeanFinder with minimal effort. I could provide a pull request. What do you think?

Christian

Christian Kaltepoth

unread,
Jan 15, 2016, 2:33:56 AM1/15/16
to togglz...@googlegroups.com
Hey,

good news. I just committed some code to togglz-spring-core and togglz-spring-web that may fix our problems. There is now a class ContextClassLoaderApplicationContextHolder which can be used to associate an ApplicationContext with the current context class loader. Basically something very similar to what Spring's ContextLoader does. I also modified the standard SpringWebBeanFinder to also try ContextClassLoaderApplicationContextHolder to look for the ApplicationContext.

All you have to do now is to call this code after Spring Boot has started up:

  ContextClassLoaderApplicationContextHolder.bind(applicationContext);

And before the Spring Boot shutdown you have to cleanup the holder like this:

  ContextClassLoaderApplicationContextHolder.release();

That's it. I guess there is some kind of API for observing these events (ApplicationListener?).

The latest snapshot version is: togglz-spring-web-2.3.0-20160115.072949-9.jar

Let me know if this works for you.

Christian

Marcel Overdijk

unread,
Jan 15, 2016, 2:41:02 AM1/15/16
to togglz-users
Thanks Christian,

I will check this out during the weekend (other duty calls today :-). An ApplicationListener should work here I think.
Btw are the snapshots deployed in a public maven?

Christian Kaltepoth

unread,
Jan 15, 2016, 3:36:08 AM1/15/16
to togglz...@googlegroups.com
Ok, great! Thanks! :)

Yes, the snapshots are deployed to the Sonatype OSS snapshot repository. All details here:


Have a nice weekend.

Christian

Marcel Overdijk

unread,
Jan 15, 2016, 3:52:22 AM1/15/16
to togglz-users
Btw can't we ContextClassLoaderApplicationContextHolder implement Sprint's ApplicationContextAware
In that way it's just a matter of adding that bean to the context I think.

Christian Kaltepoth

unread,
Jan 15, 2016, 3:56:30 AM1/15/16
to togglz...@googlegroups.com
Maybe, but this way we won't receive a shutdown event and therefor cannot release it. Calling release is very important to prevent memory leaks.

Marcel Overdijk

unread,
Jan 15, 2016, 3:57:23 AM1/15/16
to togglz-users
Hmmm ApplicationContextAware does - obviously - not support releasing the context.
I will look into an initializer.

Marcel Overdijk

unread,
Jan 15, 2016, 8:30:12 AM1/15/16
to togglz-users
Hi Christian,

Spring Boot uses different class loaders I noticed.
Based on the event (using ApplicationListener) I've added the ApplicationContent to the ContextClassLoaderApplicationContextHolder:

public class TogglzApplicationListener implements ApplicationListener {

@Override
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ContextRefreshedEvent) {
ApplicationContext applicationContext = ((ContextRefreshedEvent) event).getApplicationContext();
ContextClassLoaderApplicationContextHolder.bind(applicationContext);
} else if (event instanceof ContextClosedEvent) {
ContextClassLoaderApplicationContextHolder.release();
}
}
}

Unfortunately it was not working.

ContextRefreshedEvent
--> CL = RestartClassLoader

EmbeddedServletContainerInitializedEvent
--> CL = RestartClassLoader

Now when the SpringCoreBeanFinder kicks in the class loader is:

TomcatEmbeddedWebappClassLoader
  context: ROOT
  delegate: true
----------> Parent Classloader:
org.springframework.boot.devtools.restart.classloader.RestartClassLoader@383c22b5


(Note in this scenario I disabled the SpringBootFeatureManagerProvider)


Cheers,
Marcel

Marcel Overdijk

unread,
Jan 15, 2016, 10:02:36 AM1/15/16
to togglz-users
Btw this 'double' classloader issue seems to be a Spring Boot issue.

Christian Kaltepoth

unread,
Jan 15, 2016, 11:42:21 AM1/15/16
to togglz...@googlegroups.com
Hmmm. Seems like Spring Boot is using some custom class loading for reloading!?!

I just committed a change to ContextClassLoaderApplicationContextHolder which *could* fix this. It's just a try. Basically ContextClassLoaderApplicationContextHolder#get() now also checks parent class loaders. This *could* work. Not sure. :)


The CI server will deploy updated snapshots in a few minutes...


Christian

Marcel Overdijk

unread,
Jan 15, 2016, 6:31:34 PM1/15/16
to togglz-users
Thanks Christian this seemed to work!
So I can remove a hack that was needed to avoid this issue (https://github.com/spring-projects/spring-boot/issues/2308).

I will do some further testing but this all looks very promising.

Christian Kaltepoth

unread,
Jan 16, 2016, 12:43:28 AM1/16/16
to togglz...@googlegroups.com
Awesome! :)

I guess you can even remove your custom FeatureManagerProvider now.

Have a nice weekend

Christian

Marcel Overdijk

unread,
Jan 16, 2016, 8:51:53 AM1/16/16
to togglz-users
Sure the custom Spring Boot FeatureManagerProvider was already removed yesterday via https://github.com/marceloverdijk/togglz-spring-boot/commit/f10d5ae269d132f5fd850a25af0551f9beee0a69

Vasily Ivanov

unread,
Feb 2, 2017, 11:34:50 PM2/2/17
to togglz-users
Hi guys,

I have a custom FeatureManager that I initiate via Spring's Java Config.
With Spring Boot running in IBM WAS 8 I could only make it work with StaticFeatureManagerProvider and FEATURE_MANAGER_PROVIDED=true, otherwise Togglz just can't discover my Spring initiated feature manager.

Spring Boot standalone works just fine without either of those hacks.

Togglz3 definitely needs to take DI/Spring-first approach.

Thanks,
  Vasily

Christian Kaltepoth

unread,
Feb 3, 2017, 12:24:34 AM2/3/17
to togglz...@googlegroups.com
Hey,

I have a custom FeatureManager that I initiate via Spring's Java Config.

Actually that's a pattern I would like to promote in the future. It totally makes sense to let the DI container of choice manage the lifecycle of the feature manager.

 
With Spring Boot running in IBM WAS 8 I could only make it work with StaticFeatureManagerProvider and FEATURE_MANAGER_PROVIDED=true, otherwise Togglz just can't discover my Spring initiated feature manager.

Spring Boot standalone works just fine without either of those hacks.

Togglz tries various strategies to obtain the Spring ApplicationContext. Unfortunately that's not as easy as it sounds. For classic Spring web apps one of these mechanisms should usually work:


Not sure what is happening in your case. But debugging this code should bring some light into the issue.

Christian

Reply all
Reply to author
Forward
0 new messages