Menu Close

61.8. 動的バインディング

概要

コンテナーフィルターとコンテナーインターセプターをリソースにバインディングする標準的な方法では、フィルターとインターセプターに @Provider アノテーションを付けます。。これは、バインディングが グローバル となるようにします。つまり、フィルターとインターセプターは、サーバー側で すべて のリソースクラスとリソースメソッドにバインドされます。

動的バインディングは、サーバー側でバインディングする代替方法です。これにより、インターセプターとフィルターが適用されるリソースメソッドを選択できます。フィルターおよびインターセプターの動的バインディングを有効にするには、以下に記載されているように、カスタム DynamicFeature インターフェースを実装する必要があります。

DynamicFeature インターフェース

DynamicFeature インターフェースは、以下のように javax.ws.rx.container パッケージで定義されます。

// Java
package javax.ws.rs.container;

import javax.ws.rs.core.FeatureContext;
import javax.ws.rs.ext.ReaderInterceptor;
import javax.ws.rs.ext.WriterInterceptor;

public interface DynamicFeature {
    public void configure(ResourceInfo resourceInfo, FeatureContext context);
}

動的な機能の実装

以下のように動的機能を実装します。

  1. 前述のように、1 つ以上のコンテナーフィルターまたはコンテナーインターセプターを実装します。ただし、@Provider アノテーションを付けないでください (そうしないと、グローバルにバインドされ、動的機能が事実上無関係になります)。
  2. DynamicFeature クラスを実装して、configure メソッドをオーバーライドすることで、独自の動的な機能を作成します。
  3. configure メソッドでは、resourceInfo 引数を使用して、この機能が呼び出されているリソースクラスとリソースメソッドを検出できます。この情報は、フィルターまたはインターセプターの一部を登録するかどうかを決定するための基盤として使用できます。
  4. フィルターまたはインターセプターを現在のリソースメソッドに登録する場合は、context.register メソッドのいずれかを呼び出します。
  5. 動的機能クラスに @Provider アノテーションを付けて、デプロイメントのスキャンフェーズ中にこれが選択されるようにします。

動的機能の例

以下の例は、@GET アノテーションが付けられた MyResource クラス (またはサブクラス) のメソッドに LoggingFilter フィルターを登録する動的な機能を定義する方法を示しています。

// Java
...
import javax.ws.rs.container.DynamicFeature;
import javax.ws.rs.container.ResourceInfo;
import javax.ws.rs.core.FeatureContext;
import javax.ws.rs.ext.Provider;

@Provider
public class DynamicLoggingFilterFeature implements DynamicFeature {
  @Override
  void configure(ResourceInfo resourceInfo, FeatureContext context) {
    if (MyResource.class.isAssignableFrom(resourceInfo.getResourceClass())
      && resourceInfo.getResourceMethod().isAnnotationPresent(GET.class)) {
      context.register(new LoggingFilter());
  }
}

動的バインディングプロセス

JAX-RS 標準では、リソースメソッドごとに DynamicFeature.configure メソッドを 1 度だけ呼び出す必要があります。つまり、すべてのリソースメソッドに動的機能によってフィルタまたはインターセプターがインストールされる可能性がありますが、それぞれの場合にフィルターまたはインターセプターを登録するかどうかを決定するのは動的機能次第です。つまり、動的な機能でサポートされるバインディングの粒度は、個別のリソースメソッドのレベルになります。

FeatureContext インターフェース

FeatureContext インターフェース ( configure メソッドでフィルターおよびインターセプターを登録可能) は、以下のように Configurable<> のサブインターフェースとして定義されます。

// Java
package javax.ws.rs.core;

public interface FeatureContext extends Configurable<FeatureContext> {
}

Configurable<> インターフェースは、以下のようにフィルターおよびインターセプターを 1 つのリソースメソッドに登録するさまざまなメソッドを定義します。

// Java
...
package javax.ws.rs.core;

import java.util.Map;

public interface Configurable<C extends Configurable> {
    public Configuration getConfiguration();
    public C property(String name, Object value);
    public C register(Class<?> componentClass);
    public C register(Class<?> componentClass, int priority);
    public C register(Class<?> componentClass, Class<?>... contracts);
    public C register(Class<?> componentClass, Map<Class<?>, Integer> contracts);
    public C register(Object component);
    public C register(Object component, int priority);
    public C register(Object component, Class<?>... contracts);
    public C register(Object component, Map<Class<?>, Integer> contracts);
}