インターセプトの挙動
【以前のソース】
前回のソースではJAX-RSのインターセプタを使ってました。
自分の中ではJAX-RSとEJBを組み合わせて使っていたつもりだったのですが、
使っていたアノテーションを間違っていたようで、
単純な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アノテーションが有効になっているので、
サービスリソースから取得する方法に変更しました。