One of the mission statements of Togglz is that it should be easy to integrate into applications. As described in the Configuration chapter, this is especially easy for web applications. If you want to integrate Togglz into other environments, you will typically have to do some manual steps.
This chapter will cover how to bootstrap and use Togglz in the following environments:
Most of the strategies described in this chapter are based on the idea of implementing a custom
FeatureManagerProvider
. This SPI is used by Togglz to find the FeatureManager
for the application. You can think of the FeatureManager
as a central service
that manages the features of your application.
If you are using Togglz in a web application, the FeatureManager
will be created automatically
during application startup. During this process Togglz will try to automatically find your implementation
of the TogglzConfig
interface, which acts as the configuration for the FeatureManager
.
Depending on the environment you want to integrate Togglz into, you may have to build the FeatureManager
yourself. Fortunately Togglz provides a class called FeatureManagerBuilder
which simplifies this
process. To build a FeatureManager
that is configured using a TogglzConfig
instance,
you can use this code:
FeatureManager manager = new FeatureManagerBuilder() .togglzConfig(new MyTogglzConfig()) .build();
This is basically what Togglz does when starting up in a web application.
If you are using FeatureManagerBuilder
to create your FeatureManager
,
you don't even have to implement TogglzConfig
at all. You can also simply configure all the
aspects of Togglz by calling the corresponding methods on the builder:
FeatureManager manager = new FeatureManagerBuilder() .featureClass(MyFeaturess.class) .stateRepository(new InMemoryStateRepository()) .userProvider(new NoOpUserProvider()) .build();
Togglz uses an service provider interfaces called FeatureManagerProvider
to find the
FeatureManager
to use in the current execution context. Implementing this interface is very easy.
The only thing you have to think about is how to maintain (or obtain) the single FeatureManager
instance for your application.
The following sections will describe best practices for doing this in different environments and
advanced packaging scenarios.
Using Togglz in standalone applications requires some more work compared to applications which are deployed to an application server.
In most cases standalone applications don't have such complex classloading configurations as application
servers. Therefore you can typically use a simple singleton approach to manage the FeatureManager
.
The following example shows an implementation of the FeatureManagerProvider
that uses
this approach:
public class SingletonFeatureManagerProvider implements FeatureManagerProvider { private static FeatureManager featureManager; @Override public int priority() { return 30; } @Override public synchronized FeatureManager getFeatureManager() { if (featureManager == null) { featureManager = new FeatureManagerBuilder() .featureClass(MyFeaturess.class) .stateRepository(new InMemoryStateRepository()) .userProvider(new NoOpUserProvider()) .build(); } return featureManager; } }
To register the provider, take the fully qualified name of your implementation class and save it in a file called
META-INF/services/org.togglz.core.spi.FeatureManagerProvider
on your classpath. See
the docs of the ServiceLoader class for a
full description of the underlying mechanism.
If you want to use Togglz in an environment with EJB and/or EAR packaging and your application
server supports EJB 3.1, you can use an EJB singleton to manage the FeatureManager
. To
do so, create an EJB singleton that builds the FeatureManager
in the
@PostConstruct
method:
@Singleton public class FeatureManagerSingleton { private FeatureManager featureManager; @PostConstruct public void init() { featureManager = new FeatureManagerBuilder() .featureClass(MyFeaturess.class) .stateRepository(new InMemoryStateRepository()) .userProvider(new NoOpUserProvider()) .build(); } public FeatureManager getFeatureManager() { return featureManager; } }
Now you have to create an implementation of FeatureManagerProvider
that uses the EJB singleton
to obtain the FeatureManager
:
public class EJBSingletonFeatureManagerProvider implements FeatureManagerProvider { @Override public int priority() { return 30; } @Override public FeatureManager getFeatureManager() { try { InitialContext context = new InitialContext(); FeatureManagerSingleton singleton = (FeatureManagerSingleton) context.lookup("java:module/FeatureManagerSingleton"); return singleton.getFeatureManager(); } catch (NamingException e) { return null; } } }
To register the provider, take the fully qualified name of your implementation class and save it in a file called
META-INF/services/org.togglz.core.spi.FeatureManagerProvider
on your classpath. See
the docs of the ServiceLoader class for a
full description of the underlying mechanism.
This will work fine for the EJB module itself, because the JNDI name used to lookup the singleton is relative
to that module. If you want a shared FeatureManager
for all modules in your EAR,
you will have to change the JNDI name to something like this:
java:app/MyModule/FeatureManagerSingleton
If your EAR file also contains web applications and you want to use one shared FeatureManager
for the complete EAR, you have to perform one additional step. In the default setup Togglz automatically
creates a local FeatureManager
for a web application. To prevent this, add the following
configuration to your web.xml
:
<context-param> <param-name>org.togglz.FEATURE_MANAGER_PROVIDED</param-name> <param-value>true</param-value> </context-param>
If you add this configuration and your custom FeatureManagerProvider
is visible for your
web application, Togglz will automatically use the shared FeatureManager
maintained by
the EJB singleton.