インターセプトの挙動

【前提条件】

[環境]

【概要】

JAX-RSEJBを併用した際の
インターセプタでの制限についてです。

以前にCDIのインターセプタでセッションチェックという
エントリを書いたのですが、
一部、勘違いがあったようです。

以前のエントリ
インターセプタを使ったセッションチェック - シュンツのつまづき日記

【以前のソース】

前回のソースではJAX-RSのインターセプタを使ってました。

自分の中ではJAX-RSEJBを組み合わせて使っていたつもりだったのですが、
使っていたアノテーションを間違っていたようで、
単純なJAX-RSのサービスリソースのみだったようです。

[インターセプタ]
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;
    }
}
[サービスリソース]
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();
    }
}

【何を勘違いしたか?】

LocalBeanアノテーションを使ってEJBによるトランザクション管理が行われると思っていました。

StatlessBeanアノテーションを使うのが正しいのです。
ものすごい勘違いをしてたなぁと思い、
サービスリソースを下のように書き換えました。

package jp.glory.darts.application.resource;

import javax.ejb.Stateless;
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
@Stateless
@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();
    }
}

【変更して動かしてみたら・・・】

サービスリソースをEJBにして動かしてみたところ、
インターセプタのクラスでNullPointerExceptionが発生するようになりました。

どうやらContextアノテーションのインジェクションがうまくいってないようでした。

    @Context
    private HttpServletRequest request = null;

【挙動の違い】

以前のソースの場合、サービスリソースは
JAX-RSのインターセプタとして動いているため、
インターセプタ内でもContextアノテーションが有効になっていたようです。

今回の直したサービスリソースは
EJBのインターセプタとして動いているため、
Contextアノテーションが有効にならなかったようです。

【対策として】

サービスリソースのオブジェクトに対しては
Contextアノテーションが有効になっているので、
サービスリソースから取得する方法に変更しました。