1概要

このチュートリアルでは、

Togglz

ライブラリをSpring Bootアプリケーションで使用する方法を見ていきます。


2トグルズ



Togglz

library

は、

Feature Toggles

デザインパターンの実装を提供します。このパターンは、トグルに基づいて特定の機能が有効になっているかどうかをアプリケーションの実行時に判断できるメカニズムを持つことを意味します。

実行時に機能を無効にすることは、まだ完成していない新機能に取り組む、一部のユーザーにのみ機能へのアクセスを許可する、またはA/Bテストを実行するなど、さまざまな状況で役立ちます。

次のセクションでは、機能名を提供するアノテーションでメソッドをインターセプトするアスペクトを作成し、機能が有効になっているかどうかに応じてメソッドを実行し続けるかどうかを決定します。


3 Mavenの依存関係

Spring Bootの依存関係に加えて、

Togglz

ライブラリはSpring Boot Starter jarを提供します。

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.1.RELEASE</version>
</parent>

<dependency>
    <groupId>org.togglz</groupId>
    <artifactId>togglz-spring-boot-starter</artifactId>
    <version>2.4.1</version>
<dependency>
    <groupId>org.togglz</groupId>
    <artifactId>togglz-spring-security</artifactId>
    <version>2.4.1</version>
</dependency>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <version>1.4.194</version>
</dependency>


togglz-spring-boot-starter

、https://search.maven.org/の最新バージョンclassic/#search%7Cga%7C1%7Ctogglz%20spring%20セキュリティ[togglz-spring-security]、https://search.maven.org/classic/#search%7Cga%7C1%7Ca%3A%22spring-boot-starter -web%22[spring-boot-starter-web]、https://search.maven.org/classic/#search%7Cga%7C1%7Ca%3A%22spring-boot-starter-data-jpa%22[spring -boot-starter-data-jpa]、https://search.maven.org/classic/#search%7Cga%7C1%7Ca%3A%22spring-boot-starter-test%22[spring-boot-starter-test]、https://search.maven.org/classic/#search%7Cga%7C1%7Ca%3A%22h2%22[h2]はMaven Centralからダウンロードできます。


4トグルズの設定


togglz-spring-boot-starter

ライブラリには、

FeatureManager

などの必要なBeanを作成するための自動設定が含まれています。提供する必要がある唯一のBeanは

featureProvider

Beanです。

まず、

Feature

インターフェースを実装し、機能名のリストを含む列挙を作成しましょう。

public enum MyFeatures implements Feature {

    @Label("Employee Management Feature")
    EMPLOYEE__MANAGEMENT__FEATURE;

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

列挙体は、特定の機能が有効になっているかどうかを検証する

isActive()

というメソッドも定義します。

それからSpring Boot設定クラスで

EnumBasedFeatureProvider

型のbeanを定義できます。

@Configuration
public class ToggleConfiguration {

    @Bean
    public FeatureProvider featureProvider() {
        return new EnumBasedFeatureProvider(MyFeatures.class);
    }
}


5アスペクトの作成

次に、カスタムの

AssociatedFeature

アノテーションをインターセプトし、annotationパラメーターで提供されている機能をチェックしてアクティブかどうかを判断するアスペクトを作成します。

@Aspect
@Component
public class FeaturesAspect {

    private static final Logger LOG = Logger.getLogger(FeaturesAspect.class);

    @Around(
      "@within(featureAssociation) || @annotation(featureAssociation)"
    )
    public Object checkAspect(ProceedingJoinPoint joinPoint,
      FeatureAssociation featureAssociation) throws Throwable {

        if (featureAssociation.value().isActive()) {
            return joinPoint.proceed();
        } else {
            LOG.info(
              "Feature " + featureAssociation.value().name() + " is not enabled!");
            return null;
        }
    }
}

タイプ

MyFeatures

enumの

value()

パラメーターを持つ

FeatureAssociation

という名前のカスタムアノテーションも定義しましょう。

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.TYPE })
public @interface FeatureAssociation {
    MyFeatures value();
}

機能がアクティブな場合、アスペクトはメソッドの実行を続けます。そうでなければ、メソッドコードを実行せずにメッセージを記録します。


6. 機能のアクティベーション


Togglz

の機能はアクティブにも非アクティブにもできます。この動作は

enabled

フラグとオプションで有効化戦略によって制御されます。


enabled

フラグをtrueに設定するには、列挙値定義に

@ EnabledByDefault

アノテーションを使用できます。

また、

Togglz

ライブラリは、特定の条件に基づいて機能が有効になっているかどうかを判断するために使用できるさまざまなアクティブ化戦略を提供します。

この例では、Systemプロパティの値に基づいて機能の状態を評価するEMPLOYEE

MANAGEMENT

FEATUREに

SystemPropertyActivationStrategy

を使用します。必要なプロパティ名と値は、

@ ActivationParameter

アノテーションを使用して指定できます。

public enum MyFeatures implements Feature {

    @Label("Employee Management Feature")
    @EnabledByDefault
    @DefaultActivationStrategy(id = SystemPropertyActivationStrategy.ID,
      parameters = {
      @ActivationParameter(
        name = SystemPropertyActivationStrategy.PARAM__PROPERTY__NAME,
        value = "employee.feature"),
      @ActivationParameter(
        name = SystemPropertyActivationStrategy.PARAM__PROPERTY__VALUE,
        value = "true") })
    EMPLOYEE__MANAGEMENT__FEATURE;
   //...
}


employee.feature

プロパティの値が

true

の場合にのみ、機能を有効にするように設定しました。


Togglz

ライブラリーによって提供される他のタイプの活動化戦略は、以下のとおりです。


  • UsernameActivationStrategy

    – この機能を有効にします。

指定されたユーザーのリスト
** UserRoleActivationStrategy – 現在のユーザの役割は

機能の状態を判断する
**

ReleaseDateActivationStrategy

– で自動的に機能を有効にする

特定の日時
**

GradualActivationStrategy

– 特定の機能を有効にします。

ユーザーの割合
**

ScriptEngineActivationStrategy

– カスタムスクリプトの使用を許可

JVMの

ScriptEngine

でサポートされている言語で書かれている
機能がアクティブかどうかを判断する
**

ServerIpActivationStrategy

– IPに基づいて機能が有効になります。

サーバーのアドレス


7. アスペクトのテスト


7.1. アプリケーション例

私たちの側面を実際に見るために、組織の従業員を管理するための機能を含む簡単な例を作成しましょう。

この機能が開発されるにつれて、EMPLOYEE

MANAGEMENT

FEATUREの値で

@ AssociatedFeature

アノテーションが付けられたメソッドとクラスを追加できます。これにより、機能がアクティブな場合にのみアクセス可能になります。

まず、Spring Dataに基づいて

Employee

エンティティクラスとリポジトリを定義しましょう。

@Entity
public class Employee {

    @Id
    private long id;
    private double salary;

   //standard constructor, getters, setters
}

public interface EmployeeRepository
  extends CrudRepository<Employee, Long>{ }

次に、従業員の給料を上げるためのメソッドを含む

EmployeeService

を追加しましょう。

EMPLOYEE

MANAGEMENT

FEATURE

というパラメータを使用して、メソッドに

@ AssociatedFeature

アノテーションを追加します。

@Service
public class SalaryService {

    @Autowired
    EmployeeRepository employeeRepository;

    @FeatureAssociation(value = MyFeatures.EMPLOYEE__MANAGEMENT__FEATURE)
    public void increaseSalary(long id) {
        Employee employee = employeeRepository.findById(id).orElse(null);
        employee.setSalary(employee.getSalary() +
          employee.getSalary() **  0.1);
        employeeRepository.save(employee);
    }
}

このメソッドは、テストのために呼び出す

/reduceSalary

エンドポイントから呼び出されます。

@Controller
public class SalaryController {

    @Autowired
    SalaryService salaryService;

    @PostMapping("/increaseSalary")
    @ResponseBody
    public void increaseSalary(@RequestParam long id) {
        salaryService.increaseSalary(id);
    }
}


7.2. JUnitテスト

まず、

employee.feature

プロパティを

false

に設定した後にPOSTマッピングを呼び出すテストを追加しましょう。この場合、この機能はアクティブにしないでください。また、従業員の給与の値は変更しないでください。

@Test
public void givenFeaturePropertyFalse__whenIncreaseSalary__thenNoIncrease()
  throws Exception {
    Employee emp = new Employee(1, 2000);
    employeeRepository.save(emp);

    System.setProperty("employee.feature", "false");

    mockMvc.perform(post("/increaseSalary")
      .param("id", emp.getId() + ""))
      .andExpect(status().is(200));

    emp = employeeRepository.findOne(1L);
    assertEquals("salary incorrect", 2000, emp.getSalary(), 0.5);
}

次に、プロパティを

true

に設定した後に呼び出しを実行するテストを追加しましょう。この場合、給与の値を増やす必要があります。

@Test
public void givenFeaturePropertyTrue__whenIncreaseSalary__thenIncrease()
  throws Exception {
    Employee emp = new Employee(1, 2000);
    employeeRepository.save(emp);
    System.setProperty("employee.feature", "true");

    mockMvc.perform(post("/increaseSalary")
      .param("id", emp.getId() + ""))
      .andExpect(status().is(200));

    emp = employeeRepository.findById(1L).orElse(null);
    assertEquals("salary incorrect", 2200, emp.getSalary(), 0.5);
}


8結論

このチュートリアルでは、アスペクトを使用して

Togglz

ライブラリをSpring Bootと統合する方法を示しました。

例の完全なソースコードはhttps://github.com/eugenp/tutorials/tree/master/spring-boot[over on GitHub]にあります。