LoginSignup
4
2

More than 5 years have passed since last update.

CDIをTomcatで動かす - Weld Servlet

Last updated at Posted at 2016-10-12

概要

本来はJava EE環境(Java EE サーバ上)で動くCDIを、Tomcat(非Java EE サーバ)で動かしてみます。
CDIの参照実装であるWeldを使います。
シンプルな構成にしたいので、素のServletにDIするものとします。

今回作成したサンプルコードは、GitHubにアップしてあります。
https://github.com/sumeragizzz/weldservlet-examples

環境

Windows 10 Pro 64bit
Java SE 8 Update 102 64bit
Apache Tomcat 8.0.36 64bit
Weld Servlet 2.4.0.Final

準備

Maven

ビルドツールにMavenを使用します。
pom.xmlに以下の依存情報を追加します。

pom.xml
<dependency>
  <groupId>javax.servlet</groupId>
  <artifactId>javax.servlet-api</artifactId>
  <version>3.1.0</version>
  <scope>provided</scope>
</dependency>

<dependency>
    <groupId>org.jboss.weld.servlet</groupId>
    <artifactId>weld-servlet</artifactId>
    <version>2.4.0.Final</version>
</dependency>

前者はHttpServletなどのServlet関連クラスをコンパイル時に参照できるようにする為。
後者は今回のテーマであるCDIの実装です。

web.xml

Sevlet 3.0からは自動的にSevletを検出してくれるので、ほぼ何も定義していません。

web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
         http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
    <display-name>Archetype Created Web Application</display-name>
</web-app>

beans.xml

CDIを有効にする為、beans.xmlを用意します。
前回の投稿にも書きましたが、0byteファイルでも有効になります。
サンプルの都合でインターセプターを定義したくらいで、有効化の為に必要な定義はありません。

beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans
    xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://xmlns.jcp.org/xml/ns/javaee
        http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
    bean-discovery-mode="all">
    <interceptors>
        <class>examples.weldservlet.interceptor.ZonedInterceptor</class>
    </interceptors>
</beans>

実装

サンプルなので処理内容は特に意味の無いものになっています。

Sevletに@InjectでDIできます。

NowServlet.java
@WebServlet("/NowServlet")
public class NowServlet extends HttpServlet {
    @Inject
    private DateTimeFormatBean dateTimeFormatBean;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.getWriter().append(dateTimeFormatBean.get());
    }
}

DIしたCDI Beanに別のCDI BeanをDIできます。

DateTimeFormatBean.java
public class DateTimeFormatBean {
    @Inject
    private NowBean nowBean;

    public String get() {
        return nowBean.get().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
    }
}

別のCDI Beanはインターセプターを適用しました。

NowBean.java
@ZonedInterceptorBinding
public class NowBean {
    public ZonedDateTime get() {
        return ZonedDateTime.now();
    }
}

インターセプターの実装は下記の通り。

ZonedInterceptor.java
@Interceptor
@ZonedInterceptorBinding
public class ZonedInterceptor {
    @AroundInvoke
    public Object invoke(InvocationContext context) throws Exception {
        ZonedDateTime result = ZonedDateTime.class.cast(context.proceed());
        return result.withZoneSameInstant(ZoneId.of("America/New_York"));
    }
}
ZonedInterceptorBinding.java
@Inherited
@InterceptorBinding
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
public @interface ZonedInterceptorBinding {
}

Tomcatにデプロイして、下記のURLにブラウザからアクサスします。
http://localhost:8080/weldservlet-examples/NowServlet

ブラウザに日時が表示されたら成功です。

実行結果
2016-10-12T11:08:42.372

まとめ

pom.xmlに依存情報の追加と、beans.xmlの作成くらいなので、意外と手軽に導入できます。
ただ、実際には素のSevletを使う機会は少ないでしょう。
現実的にはJAX-RSなどとの組み合わせになるので、いずれこちらも投稿したいと思います。

参考

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2