3

Since version 2.0.0 Togglz offers Activation Strategies to go with a feature. For instance, you can connect a list of server IP addresses that shall have the feature enabled. However, how are these strategies actually attached to a feature? All I saw was that I can change the strategy in the Togglz console or even edit the data by hand in the database.

What I was looking for is some default mechanism rather similar to @EnabledByDefault. I could implement a custom state repository, it could even look for annotations, but I suspected that this solution existed out of the box.

Michael Piefel
  • 18,660
  • 9
  • 81
  • 112

2 Answers2

5

Just to share my own solution.

An annotation for defaults

I defined annotations that should be used the way @EnabledByDefault is. Here is one for the server-ip strategy:

/**
 * Allows to specify that the annotated feature should use
 * {@link ServerIPStrategy} if the repository doesn't have any
 * state saved.
 * 
 * @author Michael Piefel
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface UsingServerIPStrategy {

    /**
     * A comma-separated list of server IPs for which
     * the feature should be active.
     */
    String value();

}

Using the annotation

In the feature definition, use the annotion like this:

…
@EnabledByDefault
@UsingServerIPStrategy(value = "192.168.1.211")
@Label("Run regular jobs to send status e-mails to participants")
MAIL_CRON_JOBS;
…

State repository to evaluate

I want to take the feature state from a repository if it already has been saved. If not, the annotations must be evaluated. For this, a delegation repository is needed:

/**
 * A Togglz {@link StateRepository} that looks for default strategies
 * on the defined features.
 * 
 * @author Michael Piefel
 */
@AllArgsConstructor
public class DefaultingStateRepository implements StateRepository {

    private StateRepository delegate;

    @Override
    public FeatureState getFeatureState(Feature feature) {
        FeatureState featureState = delegate.getFeatureState(feature);
        if (featureState == null) {
            // Look for a default strategy.
            // If none is defined, a null return value is good enough.
            UsingServerIPStrategy serverIPStrategy = FeatureAnnotations
                    .getAnnotation(feature, UsingServerIPStrategy.class);
            if (serverIPStrategy != null) {
                featureState = new FeatureState(feature,
                        FeatureAnnotations.isEnabledByDefault(feature));
                featureState.setStrategyId(ServerIpActivationStrategy.ID);
                featureState.setParameter(ServerIpActivationStrategy.PARAM_IPS,
                        serverIPStrategy.value());
            }
        }

        return featureState;
    }

    @Override
    public void setFeatureState(FeatureState featureState) {
        // write through
        delegate.setFeatureState(featureState);
    }
}

Wiring is it in

Finally, to use the repository, I wired it in our TogglzConfig component, deferring to JDBC, but letting it be cached as well:

…
@Override
public StateRepository getStateRepository() {
    JDBCStateRepository jdbcStateRepository = new JDBCStateRepository(dataSource);
    DefaultingStateRepository defaultingStateRepository = new
            DefaultingStateRepository(jdbcStateRepository);
    return new CachingStateRepository(defaultingStateRepository, 60_000);
}
…
Michael Piefel
  • 18,660
  • 9
  • 81
  • 112
  • 2
    Hey. I'm the author of Togglz. Sorry for answering that late. It's correct that Togglz currently only supports to enable a feature by default without any strategy. To be honest, I'm not a big fan of complex default states. In my experience defaults typically differ between environments, which makes it even harder to find a common way for declaring defaults. But perhaps there should be an SPI for the default states that can be customized more easily. If you think that makes sense, feel free to open a issue for that. BTW: Thanks for sharing your solution with the community. – chkal Aug 25 '13 at 17:01
0

@DefaultActivationStrategy can be added to set an activation strategy as default. Also, you can set default values to the strategy. Example:

@EnabledByDefault

@Label("UserNotification")

@DefaultActivationStrategy(
    id = UserNotificationActivationStrategy.ID,
    parameters = {
        @ActivationParameter(name = UserNotificationActivationStrategy.LICENSE_TYPE, value ="PRO")
    }
);

UserNotificationActivationStrategy is the user defined activation strategy.

refer : https://github.com/eugenp/tutorials/blob/master/spring-boot/src/main/java/com/baeldung/toggle/MyFeatures.java https://www.togglz.org/apidocs/2.3.0.final/org/togglz/core/annotation/defaultactivationstrategy

Naik Ashwini
  • 750
  • 12
  • 32