Help us understand the problem. What is going on with this article?

CDIをTomcatで動かす - Weld Servlet

More than 3 years have passed since last update.

概要

本来は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などとの組み合わせになるので、いずれこちらも投稿したいと思います。

参考

http://docs.jboss.org/weld/reference/latest/en-US/html_single/

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした