インターセプタを使ったセッションチェック

【前提条件】

[環境]

【概要】

JAX-RSのサービスエンドポイントの実行を行う前に、
セッションのチェックを行うようにします。

このインターセプタの後日談
インターセプトの挙動 - シュンツのつまづき日記

アノテーション

アノテーションは二つ作成します。
InterceptorBindingを行うためのアノテーション
セッションチェックの有無を設定するアノテーションです。

[InterceptorBindingアノテーション]
package jp.glory.darts.application.interceptor.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import javax.interceptor.InterceptorBinding;


@InterceptorBinding
@Target({
    ElementType.TYPE
})
@Retention(RetentionPolicy.RUNTIME)
public @interface SampleServiceEndPoint {

}

セッションチェック有無の設定も
こちらのアノテーションに埋め込みたかったのですが、
InterceptorBindingはvalueを持たないアノテーションのみのようです。

[セッションチェックアノテーション]
package jp.glory.darts.application.interceptor.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({
    ElementType.TYPE
})
@Retention(RetentionPolicy.RUNTIME)
public @interface SampleServiceEndPointConfig {

    public boolean isCheckSession() default true;
}

こちらのアノテーション
各サービスエンドポイントでセッションチェックを行うかの設定を
クラス定義の箇所で指定します。

【インターセプタ】

package jp.glory.darts.application.interceptor;

import java.lang.reflect.Method;

import javax.interceptor.AroundInvoke;
import javax.interceptor.Interceptor;
import javax.interceptor.InvocationContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.ws.rs.core.Context;

import jp.glory.darts.application.interceptor.annotation.SampleServiceEndPoint;
import jp.glory.darts.application.interceptor.annotation.SampleServiceEndPointConfig;
import jp.glory.darts.session.SessionKey;
import jp.glory.darts.view.login.LoginView;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.sun.jersey.api.view.Viewable;

@Interceptor
@SampleServiceEndPoint
public class ServiceEndPointInterceptor {

    @Context
    private HttpServletRequest request = null;

    public Object invokeAround(final InvocationContext context) {

        final Method method = context.getMethod();
        final Class<? extends Object> targetClass = method.getDeclaringClass();

        final SampleServiceEndPointConfig config = targetClass.getAnnotation(SampleServiceEndPointConfig.class);

        try {

            final Object returnObject = proceedService(context, config);

            return returnObject;
        } catch (final Throwable error) {

            handleException(error);
            return null;
        }
    }


    private Object proceedService(final InvocationContext context, final SampleServiceEndPointConfig config)
            throws Exception {

        Object returnObject = null;

        // セッションのチェック
        if (checkSession(config)) {

            returnObject = context.proceed();
        } else {

            // セッションタイムアウトの処理
        }

        return returnObject;
    }
}
[requestのインジェクション]

インターセプタ内部でもContextアノテーションが使用でき、
HttpservletRequestのオブジェクトをインジェクションできます。

JAX-RS(Jersey)の場合、requestはThreadLocalによって値が保持されます。

【サービスエンドポイント】

package jp.glory.darts.application.resource;

import javax.ejb.LocalBean;
import javax.enterprise.context.RequestScoped;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Context;

import jp.glory.darts.application.ApplicationConstant;
import jp.glory.darts.application.interceptor.annotation.SampleServiceEndPoint;
import jp.glory.darts.application.interceptor.annotation.SampleServiceEndPointConfig;
import jp.glory.darts.view.login.LoginView;

import com.sun.jersey.api.view.Viewable;


@Path(ApplicationConstant.SERVICE_ROOT)
@RequestScoped
@LocalBean

// セッションチェック用のアノテーション
@SampleServiceEndPoint
@SampleServiceEndPointConfig(isCheckSession = false)
public class IndexService {

    @Context
    private HttpServletRequest request = null;


    @GET
    public Viewable index() {

        final LoginView view = new LoginView();
        view.setRequest(request);

        return view.createViewable();
    }
}

各サービスエンドポイントとなるクラスでは
独自に作成した二つのアノテーションをつけます。