Can Togglz more than one activation strategy be associated with a feature?

748 views
Skip to first unread message

Chris

unread,
Oct 13, 2015, 11:55:16 PM10/13/15
to togglz-users
Here is an example scenario that would be common for our product:
- To allow for beta testing turn on a specific feature to a select set of tenants
- If beta testing goes well continue to allow the beta tenants to have access and progressively roll out on a percentage basis to everyone else

First use a custom strategy that allows for the selection of tenants would need to be associated.  Then later add a second custom strategy would need to be added which would allow for a percentage based roll out.

Steele, Richard

unread,
Oct 16, 2015, 2:14:50 PM10/16/15
to togglz...@googlegroups.com
I agree this would be great to have.  In fact, I implemented a composite activation strategy as a custom class.  It wasn't too hard, but the biggest problem is that the configuration (using properties files) is....messy.

Christian Kaltepoth

unread,
Oct 19, 2015, 11:25:07 AM10/19/15
to togglz...@googlegroups.com
Sorry for the delayed response.

It's correct that Togglz currently only supports one activation strategy for each feature. To be honest I'm not convinced yet that adding support for multiple strategies is a good idea. It would be a major API break I guess.

My recommendation is to follow Richard's idea and implement a composite strategy for that. That should really be very easy. I think we could perhaps provide some base class that simplifies creating it even further.

Christian

Charith De Silva

unread,
Jul 20, 2016, 11:33:57 PM7/20/16
to togglz-users
Hi Chris 

I'm in the similar need of having overloaded strategies for a given feature. Can you please elaborate how I can implement this with minimum effort and having console to reflect the selected strategies too. 

cheers
Charith 

Christian Kaltepoth

unread,
Jul 21, 2016, 3:20:11 AM7/21/16
to togglz...@googlegroups.com
Hey,

Basically you just have to create a custom strategy like described in the documentation:


And the implementation should basically combine two "child" strategies like this:
  • isActive(): Call isActive() on both "child" strategies. Return true if both return true.
  • getParameters(): Call isParameters() on both child strategies and return a list containing all parameters.
That's all. ;-)

Christian

Charith De Silva

unread,
Jul 25, 2016, 2:45:19 AM7/25/16
to togglz...@googlegroups.com
Hi Christian 

Thanks for your reply. Heading into my next issue. I have EAR packaging. I've Togglz working perfectly for web context(WAR). Now I need to make this available for application context too. Application is written is wired through spring. No EJBs though. Can you please let me know the best approach to use togglz in such structure? 

Thanks 
Charith 

Christian Kaltepoth

unread,
Jul 25, 2016, 3:40:01 AM7/25/16
to togglz...@googlegroups.com
I'm not very familiar with Spring to be honest. The question is if you can define a Spring managed bean in some global context for the EAR. Is there a global application context in your setup?

Charith De Silva

unread,
Jul 26, 2016, 1:04:58 AM7/26/16
to togglz-users

Thanks Christian. I've got it working in EAR. Basically I've followed the standalone way to trigger this on the application context. You need to make sure to exclude the servlet, core from the web context ( i.e. through web pom file). Using spi i've loaded my spring togglzConfiguration through feature manager builder and I'm back online again for the entire application ;) 

Thanks again for help. 

public class SingletonFeatureManagerProvider implements FeatureManagerProvider {

    private static FeatureManager featureManager;

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

    @Override
    public synchronized FeatureManager getFeatureManager() {
   
        TogglzConfig togglzConfig = ContextAware.getBean(TogglzConfiguration.class); // initialize spring bean 
        
        if (featureManager == null) {
            featureManager = new FeatureManagerBuilder().togglzConfig(togglzConfig).build();
        }

        return featureManager;

    }

}

Charith De Silva

unread,
Jul 28, 2016, 9:30:53 PM7/28/16
to togglz-users
Hi Christian 

Thanks for the post. I've done a base strategy class that can mix and match strategies through spring config. So if you are on spring, you can create many composite strategies as possible without touching java code. Sharing configuration for future users. cheers!

  <!-- Togglz composite strategies -->
<bean id="demoCuzStrategy1" class="myservice.togglz.ActivationStrategyBase">
<property name="name" value="Demo Strategy 1" />
<property name="id" value="demo1" />
   <property name="activationStrategies">
       <list value-type="org.togglz.core.spi.ActivationStrategy">
           <ref bean="myTestActivationStrategy"/>
           <ref bean="usernameActivationStrategy"/>
       </list>
    </property>
</bean>

 
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.togglz.core.activation.Parameter;
import org.togglz.core.repository.FeatureState;
import org.togglz.core.spi.ActivationStrategy;
import org.togglz.core.user.FeatureUser;

/**
 * <p>
 * This Base activation strategy implementation can be used to composite custom strategies through spring application context.
 * You can mix-match both custom strategies and togglz built-in strategies to build up custom strategies without touching java code.  
 * </p>
 * 
 * @author cdesilva
 */
public class ActivationStrategyBase implements ActivationStrategy{

    public String id;
    public String name;
    
private List<ActivationStrategy> activationStrategies;
    
    @Override
    public String getId() {
        return id;
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public boolean isActive(FeatureState featureState, FeatureUser user) {
   
    boolean isActive = true; 
    // Validate all composite strategies. 
    for (ActivationStrategy strategy : activationStrategies) {
    if (!strategy.isActive(featureState, user)) {
    isActive = false;
    break; 
    }
    }

        return isActive;
    }

    @Override
    public Parameter[] getParameters() {
    List<Parameter> parametersList = new ArrayList<>();
   
    // Collect parameters from composite strategies.
    for (ActivationStrategy strategy : activationStrategies) {
    parametersList.addAll(new ArrayList<Parameter>(
    Arrays.asList(strategy.getParameters())));
    }
   
    return parametersList.toArray(new Parameter[parametersList.size()]);
    }

public List<ActivationStrategy> getActivationStrategies() {
return activationStrategies;
}

public void setActivationStrategies(
List<ActivationStrategy> activationStrategies) {
this.activationStrategies = activationStrategies;
}

public void setId(String id) {
this.id = id;
}

public void setName(String name) {
this.name = name;
}
}

Christian Kaltepoth

unread,
Jul 30, 2016, 5:36:06 AM7/30/16
to togglz...@googlegroups.com
Great, thanks for sharing! :-)
Reply all
Reply to author
Forward
0 new messages