CDIによる連携

今回はCDIによる連携です。

【前提条件】

[環境]

【概要】

JSFEJBJPACDIの連携です。

【サンプルコード】

[テーブル]

今回は「userdata」テーブルを使います。

CREATE TABLE userdata
(
    user_id character varying(10) NOT NULL,
    name character varying(60),
    last_update timestamp with time zone NOT NULL DEFAULT now(),
    CONSTRAINT user_primary_key PRIMARY KEY (user_id )
)
[ページ]

ユーザ一覧を表示すためのページです。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html">
    <f:view>
        <h:form id="searchForm">
            <h:dataTable value="#{userListPage.getUserList()}" var="user">
                <h:column>
                    <f:facet name="header">
                        ユーザID
                    </f:facet>
                    <h:outputText value="#{user.userId}" />
                </h:column>
                <h:column>
                    <f:facet name="header">
                        ユーザ名
                    </f:facet>
                    <h:outputText value="#{user.name}" />
                </h:column>
            </h:dataTable>
        </h:form>
    </f:view>
</html>
[ManagedBean]

ユーザ一覧を表示するためのManagedBeanです。

package jp.glory.ui;

import java.util.List;

import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.inject.Named;

import jp.glory.application.UserApplication;
import jp.glory.infrastructure.persistence.entity.UserData;

@Named(value = "userListPage")
@RequestScoped
public class UserListPage {

    @Inject
    private UserApplication applicaiton = null;

    public List<UserData> getUserList() {
        return applicaiton.findAllList();
    }

}

前回と変わりません。

Namedアノテーション
CDIのRequestScopedアノテーションを使用して、
ManagedBeanのインジェクション設定を行っています。

Injectアノテーションを使用して、
UserApplicationインターフェイスに対してインジェクションしています。

上記のコードは下記のコードとほぼ同じです。

import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;

@ManagedBean(name = "userListPage")
@RequestScoped
public class UserListPage {
    // 処理部分は省略
}
[EJB]

まずはインターフェイスです。

package jp.glory.application;

import java.util.List;

import jp.glory.infrastructure.persistence.entity.UserData;

public interface UserApplication {

    List<UserData> findAllList();
}

これも前回と変わりません。

続いてクラスです。

package jp.glory.application.impl;

import java.util.List;

import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;

import jp.glory.application.UserApplication;
import jp.glory.infrastructure.persistence.entity.UserData;

@Stateless
@LocalBean
public class UserApplicationImpl implements UserApplication {

    @PersistenceContext(unitName = "blog")
    private EntityManager manager = null;

    @Override
    public List<UserData> findAllList() {

        final TypedQuery<UserData> query = manager.createNamedQuery("findAll", UserData.class);

        return query.getResultList();
    }
}

通常のEJBと同じくStateLessアノテーションをつけています。

JPAのインジェクションも
PersistenceContextアノテーションを使います。

[エンティティ]

エンティティクラスです。

package jp.glory.infrastructure.persistence.entity;

import java.io.Serializable;
import java.sql.Timestamp;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinColumns;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
@Table(name = "userdata")
@NamedQueries({
        @NamedQuery(name = "findAll", query = "SELECT u FROM UserData u"),
        @NamedQuery(name = "findByUserId", query = "SELECT u FROM UserData u WHERE u.userId = :userId"),
})
public class UserData implements Serializable {

    private static final long serialVersionUID = 6528642302239465812L;

    @Id
    @Column(name = "user_id")
    private String userId = null;

    private String name = null;

    @Column(name = "last_update")
    private Timestamp lastUpdate = null;

    // アクセサメソッドは省略
}

こちらも通常のJPAのエンティティです。

[persistence.xml]
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
    xmlns="http://java.sun.com/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
    http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">

    <persistence-unit name="blog" transaction-type="JTA">
        <jta-data-source>jdbc/blog</jta-data-source>
        <shared-cache-mode>NONE</shared-cache-mode>
    </persistence-unit>
</persistence>

JPA単体の時はclassタグを使用して、
エンティティクラスを指定していましたが、
CDIが自動的にインジェクションしてくれるので設定は不要です。

[実行]

作成したページにアクセスしてみます。

[まとめ]

今までJSFEJBJPAと個別に設定をしていたものを
CDIがまとめて設定してくれています。

CDIの設定自体はbeans.xmlをMETA-INFの配下に置くだけという
非常に簡単な作業だけです。