1.2. 最初の Seam アプリケーション: 登録サンプル


登録サンプルは新しいユーザーがそのユーザー名や実名、 パスワードをデータベースに保存できるシンプルなアプリケーションです。 このサンプルでは基本的機能のみを使用し、JSF アクションリスナーとしての EJB3 セッション Bean の使用や、Seam の基本設定を示しています。
最初のページは 3 つの入力フィールドを持つ基本的なフォームを表示します。 試しに、 項目を入力してフォームをサブミットしてください。 ユーザーオブジェクトがデータベースに保存されます。

1.2.1. コードの理解

このサンプルは 2 つの Facelets テンプレートが実装されています。 エンティティ Bean がひとつとステートレスセッション Bean がひとつです。 本項ではコードを詳細に見ていきます。 まずベースレベルから見てみましょう。

1.2.1.1. エンティティ Bean: User.java

ユーザーデータ用に EJB エンティティ Bean が必要です。 このクラスはアノテーションによって 永続性データ妥当性検証 を宣言的に定義しています。 また、 Seam コンポーネントとしてのクラスを定義するために別にいくつかのアノテーションも必要です。

例1.1 User.java

@Entity                                             
@Name("user")                                       
@Scope(SESSION)                                     
@Table(name="users")                                
public class User implements Serializable
{
    private static final long serialVersionUID =
        1881413500711441951L;
            
    private String username;                        
    private String password;
    private String name;
            
    public User(String name,
                String password,
                String username)
    {
        this.name = name;
        this.password = password;
        this.username = username;
    }
            
    public User() {}                                
            
    @NotNull @Length(min=5, max=15)                 
    public String getPassword()
    {
        return password;
    }

    public void setPassword(String password)
    {
        this.password = password;
    }
            
    @NotNull
    public String getName()
    {
        return name;
    }

    public void setName(String name)
    {
        this.name = name;
    }
            
    @Id @NotNull @Length(min=5, max=15)             
    public String getUsername()
    {
        return username;
    }

    public void setUsername(String username)
    {
        this.username = username;
    }

}
Copy to Clipboard Toggle word wrap

1

EJB3 標準 @Entity アノテーションは、 User クラスがエンティティ Bean であることを示しています。

2

Seam コンポーネントには @Name アノテーションで指定される コンポーネント名 が必要です。この名前は Seam アプリケーション内で一意である必要があります。JSF が Seam に Seam コンポーネント名と同じ名前を持つコンテキスト変数を解決するよう指示し、コンテキスト変数が現在未定義 (null) である場合、Seam はそのコンポーネントをインスタンス化し、新しいインスタンスをコンテキスト変数にバインドします。この場合、JSF が user という変数に初めて出会うときに Seam が User をインスタンス化します。

3

Seam がコンポーネントをインスタンス化すると必ず、新しいインスタンスをコンポーネントの default context のコンテキスト変数にバインドします。デフォルトのコンテキストは @Scope アノテーションを使用して指定されます。User Bean はセッションスコープのコンポーネントです。

4

EJB 標準 @Table アノテーションは、 User クラスが users テーブルにマッピングされることを示しています。

5

namepasswordusername はエンティティ Bean の永続属性です。すべての永続属性は、アクセサメソッドを定義します。これはレスポンス出力フェーズおよびモデル値の更新フェーズで JSF によりこのコンポーネントが使用されるときに必要です。

6

空のコンストラクタは、EJB 仕様と Seam の両方で必要です。

7

@NotNull@Length アノテーションは、 Hibernate Validator フレームワークの一部です。 Seam は Hibernate Validator を統合するため、 データの妥当性検証にこれを使用することができます (永続性に Hiberenate を使用していない場合でも使用できます)。

8

EJB 標準 @Id アノテーションは、 エンティティ Bean の主キーであることを示しています。
このサンプルで、最も注目してほしい重要なものは @Name@Scope アノテーションです。 このアノテーションは、このクラスが Seam コンポーネントであることを規定しています。
次項では、 User クラスのプロパティが直接 JSF コンポーネントにバインドされ、モデル値の更新フェーズで JSF により埋められていることがわかります。 JSP ページとエンティティ Bean ドメインモデル間でデータのコピーを何度も行うためのグルーコードは必要ありません。
ただし、 エンティティ Bean はトランザクション管理やデータベースアクセスを行わないので、 このコンポーネントを JSF のアクションリスナーとしては使用しないでください。 この場合、 セッション Bean の方がよいでしょう。

1.2.1.2. ステートレスセッション Bean クラス: RegisterAction.java

ほとんどの Seam アプリケーションではセッション Bean が JSF アクションリスナーとして使用されますが、 JavaBean を使用しても構いません。
このアプリケーションにはちょうどひとつだけ JSF アクションがあり、これにセッション Bean メソッドがひとつリンクしています。この場合、 アクションに関連付けられた状態はすべて User Bean で保持されるためステートレスセッション Bean を使用します。
関連コードを以下に示します。

例1.2 RegisterAction.java

@Stateless                                                                               
@Name("register")
public class RegisterAction implements Register
{
    @In                                                                                  
    private User user;
            
    @PersistenceContext                                                                  
    private EntityManager em;
            
    @Logger                                                                              
    private Log log;
            
    public String register()                                                             
    {
        List existing = em.createQuery("select username " +
                                       "from User " +
                                       "where username = #{user.username}")              
            .getResultList();
            
        if (existing.size()==0)
            {
                em.persist(user);
                log.info("Registered new user #{user.username}");                        
                return "/registered.xhtml";                                              
            }
        else
            {
                FacesMessages.instance().add("User #{user.username} already exists");    
                return null;
            }
    }

}
Copy to Clipboard Toggle word wrap

1

EJB @Stateless アノテーションはこのクラスがステートレスセッション Bean であることを示しています。

2

@In アノテーションは Bean の属性を Seam でインジェクトされているとマークします。この場合、属性は user (インスタンス変数名) という名前のコンテキスト変数からインジェクトされます。

3

EJB 標準 @PersistenceContext アノテーションは、 EJB3 エンティティマネージャにインジェクトするために使用されます。

4

Seam @Logger アノテーションはコンポーネントの Log インスタンスをインジェクトするために使用されます。

5

アクションリスナーメソッドは標準 EJB3 EntityManager API を使用して、データベースとのやり取りを行い JSF 結果を返します。 これはセッション Bean であるため、register() メソッドが呼び出されるとトランザクションは自動的に開始され、 このメソッドが終了するとトランザクションがコミットされる点に注意してください。

6

Seam では EJB-QL 内で JSF EL 式を使用することができる点に注目してください。これにより普通の JPA setParameter() が標準 JPA Query オブジェクトで呼び出されることになります。

7

Log API によりテンプレートから作成されたログメッセージを簡単に表示することができ、JSF EL 式を使用することも可能です。

8

JSF アクションリスナーメソッドは、次にどのページを表示するかを決定する文字列値の結果を返します。 null の結果 (あるいは void アクションリスナーメソッド) の場合は前のページを再表示します。純粋な JSF では、 常に JSF ナビゲーションルール を使用してその結果から JSF ビュー ID を決定するのが普通です。 複雑なアプリケーションの場合はこの間接化が役立ち、適した方法となります。ただし、このような非常に簡単なサンプルの場合 Seam では結果として JSF ビュー ID を使用することができるため、ナビゲーションルールは必要なくなります。結果としてビュー ID を使用している場合は Seam は常にブラウザリダイレクトを行う点に注意してください

9

Seam は一般的な問題の解決に役立つ 組み込みコンポーネント をいくつか提供しています。FacesMessages コンポーネントを使用すると、テンプレートで作成したエラーや成功のメッセージを表示することは容易です (Seam 2.1 では代わりに StatusMessages を使用して JSF へのセマンティック依存を取り除くことが可能です)。Seam 組み込みコンポーネントはインジェクションで取得するか、組み込みコンポーネントのクラスで instance() メソッドを呼び出すことで取得できます。
ここでは @Scope を明示的に指定していないので注意してください。 各 Seam コンポーネントタイプにはデフォルトのスコープがあり、明示的にスコープが指定されない場合に使用されます。ステートレスセッション Bean では、デフォルトスコープはステートレスコンテキストです。
セッション Bean のアクションリスナーはこの小さなアプリケーションのビジネスロジックと永続ロジックを実行しています。 さらに複雑なアプリケーションでは、別々のサービス層が必要になるかもしれませんが、 Seam ではアプリケーションの階層化に独自のストラテジーを実装することができます。必要に応じてアプリケーションをシンプルにすることも複雑にすることも自在です。

注記

このアプリケーションは明確なサンプルコードを提示する目的で必要以上に複雑になっています。 アプリケーションコードはすべて Seam のアプリケーションフレームワークコントローラを使用すると除外できます。

1.2.1.3. セッション Bean ローカルインタフェース : Register.java

セッション Bean にはローカルインターフェースが必要です。

例1.3 Register.java

@Local
public interface Register
{
     public String register();
}
Copy to Clipboard Toggle word wrap
Java コードは以上です。 次は ビューを見ましょう。

1.2.1.4. ビュー : register.xhtml と registered.xhtml

JSF に対応する技術であればいずれを使用しても Seam アプリケーションのビューページを実装することができます。 このサンプルでは Facelets で記述しました。

例1.4 register.xhtml

<?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:s="http://jboss.com/products/seam/taglib"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core">

  <head>
    <title>Register New User</title>
  </head>
  <body>
    <f:view>
      <h:form>
        <s:validateAll>
          <h:panelGrid columns="2">
            Username: <h:inputText value="#{user.username}" 
            required="true"/>
            Real Name: <h:inputText value="#{user.name}" 
            required="true"/>
            Password: <h:inputSecret value="#{user.password}" 
            required="true"/>
          </h:panelGrid>
        </s:validateAll>
        <h:messages/>
        <h:commandButton value="Register" action="#{register.register}"/>
      </h:form>
    </f:view>
  </body>

</html>
Copy to Clipboard Toggle word wrap
ここで Seam 固有のタグとなるのは <s:validateAll> のみです。 この JSF コンポーネントは含まれるすべての入力フィールドをエンティティ Bean で指定される Hibernate Validator のアノテーションに対して検証するよう JSF に指示します。

例1.5 registered.xhtml

<?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">

  <head>
    <title>Successfully Registered New User</title>
  </head>
  <body>
    <f:view>
      Welcome, #{user.name}, you are successfully 
      registered as #{user.username}.
    </f:view>
  </body>

</html>
Copy to Clipboard Toggle word wrap
上記はインライン EL で作成したシンプルな Facelets ページです。 Seam 固有のものは何も含まれていません。

1.2.1.5. Seam コンポーネントデプロイメント記述子 : components.xml

デプロイメント記述子を見ていく前に、 Seam が最小限の設定を非常に重視していることは注目に値します。 これらの設定ファイルは Seam アプリケーションを作成すると自動的に生成されます。また、これらの設定ファイルを変更する必要性が生じることはめったにないでしょう。 ここに設定ファイルを示す目的は、 単に全サンプルコードの目的と機能の理解に役立てていただくためだけです。
以前に Java フレームワークを使用したことがある方なら、 XML ファイルにコンポーネントクラスを宣言することにも慣れていくことでしょう。 また プロジェクトが進化するに従い XML ファイルの管理が難しくなっていくことに気付かれると思います。 幸い、 Seam ではアプリケーションコンポーネントに XML を付随する必要がありません。 ほとんどの Seam アプリケーションは XML のほんの一部しか必要とせず、 プロジェクトが拡大してもこのサイズが増大していくことはありません。
ただし、 特定のコンポーネント、 特に Seam に組み込まれるコンポーネントなどに関する何らかの外部設定を提供できると便利な場合がよくあります。最も柔軟性のあるオプションは、WEB-INF ディレクトリにある components.xml と呼ばれるファイルにこの設定を与えることです。 components.xml ファイルを使用して Seam に JNDI での EJB コンポーネントの検索方法を指示することができます。

例1.6 components.xml のサンプル

<?xml version="1.0" encoding="UTF-8"?>
<components xmlns="http://jboss.com/products/seam/components"
            xmlns:core="http://jboss.com/products/seam/core"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation=
            "http://jboss.com/products/seam/core
             http://jboss.com/products/seam/core-2.2.xsd 
             http://jboss.com/products/seam/components
             http://jboss.com/products/seam/components-2.2.xsd">
  
  <core:init jndi-pattern="@jndiPattern@"/>
  
</components>
Copy to Clipboard Toggle word wrap
上記のコードは org.jboss.seam.core.init という名前の Seam 組み込みコンポーネントに属する jndiPattern という名前のプロパティを設定します。 アプリケーションがデプロイされるときに、 @ 記号を使って Ant ビルドスクリプトが components.properties ファイルから正しい JNDI パターンを挿入するよう指示しています。 このプロセスの詳細については components.xml によるコンポーネントの設定」 を参照してください。

1.2.1.6. WEB デプロイメント記述子 : web.xml

この小さなアプリケーションのプレゼンテーション層は WAR にデプロイされます。 したがって、 Web デプロイメント記述子が必要です。

例1.7 web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation=
         "http://java.sun.com/xml/ns/javaee
          http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         version="2.5">

  <listener>
    <listener-class>org.jboss.seam.servlet.SeamListener</listener-class>
  </listener>
  
  <context-param>
    <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
    <param-value>.xhtml</param-value>
  </context-param>
  
  <servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>*.seam</url-pattern>
  </servlet-mapping>
  
  <session-config>
    <session-timeout>10</session-timeout>
  </session-config>

</web-app>
Copy to Clipboard Toggle word wrap
上記の web.xml ファイルは Seam と JSF の両方を設定します。 ここで見る設定は Seam のアプリケーション間でほとんど変わりません。

1.2.1.7. JSF 設定 : faces-config.xml

ほとんどの Seam アプリケーションはプレゼンテーション層として JSF ビューを使用します。 従って通常 faces-config.xml が必要です。 この場合、 ビュー定義に Facelets を使用しますので、JSF にテンプレートエンジンとして Faceles を使用することを指示する必要があります。

例1.8 faces-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation=
              "http://java.sun.com/xml/ns/javaee
               http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd"
              version="1.2">

  <application>
    <view-handler>com.sun.facelets.FaceletViewHandler</view-handler>
  </application>
  
</faces-config>
Copy to Clipboard Toggle word wrap
管理 Bean はアノテーション付きの Seam コンポーネントであるため、 JSF 管理 Bean 宣言は必要ないので注意してください。 Seam アプリケーションでは faces-config.xml の使用頻度は純粋な JSF に比べると非常に少なくなります。 ここでは Facelets (および JSP 以外) をビューハンドラとして有効にするためだけに使用します。
基本的な記述子の設定がすべて完了すると、 Seam アプリケーションに機能を追加するため記述する必要がある XML は ナビゲージョンルールまたは jBPM プロセス定義の編成に対してのみとなります。 Seam は プロセスフロー設定データ はすべて XML に属するという原則で動作します。
上記のサンプルではビュー ID がアクションコードに埋め込まれているためナビゲーションルールは必要ありません。

1.2.1.8. EJB デプロイメント記述子 : ejb-jar.xml

ejb-jar.xml ファイルはアーカイブ中のすべてのセッション Bean に SeamInterceptor を付加することによって Seam を EJB3 と統合します。

例1.9 ejb-jar.xml

<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar xmlns="http://java.sun.com/xml/ns/javaee" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xsi:schemaLocation=
         "http://java.sun.com/xml/ns/javaee
          http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd"
         version="3.0">
  
  <interceptors>
    <interceptor>
      <interceptor-class>
        org.jboss.seam.ejb.SeamInterceptor
      </interceptor-class>
    </interceptor>
  </interceptors>
  
  <assembly-descriptor>
    <interceptor-binding>
      <ejb-name>*</ejb-name>
      <interceptor-class>
        org.jboss.seam.ejb.SeamInterceptor
      </interceptor-class>
    </interceptor-binding>
  </assembly-descriptor>
  
</ejb-jar>
Copy to Clipboard Toggle word wrap

1.2.1.9. EJB 永続デプロイメント記述子 : persistence.xml

persistence.xml ファイルは EJB 永続プロバイダに適切なデータソースを指示し、 またベンダー固有の設定を含んでいます。 このサンプルでは、 起動時に自動スキーマエキスポートを有効にします。

例1.10 persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence 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_1_0.xsd" 
             version="1.0">

  <persistence-unit name="userDatabase">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <jta-data-source>java:/DefaultDS</jta-data-source>
    <properties>
      <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
    </properties>
  </persistence-unit>
  
</persistence>
Copy to Clipboard Toggle word wrap

1.2.1.10. EAR デプロイメント記述子 : application.xml

最後に、EAR としてアプリケーションがデプロイされるため、 デプロイメント記述子も必要になります。

例1.11 登録アプリケーション

<?xml version="1.0" encoding="UTF-8"?>
<application xmlns="http://java.sun.com/xml/ns/javaee" 
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation=
             "http://java.sun.com/xml/ns/javaee
              http://java.sun.com/xml/ns/javaee/application_5.xsd"
             version="5">
  
  <display-name>Seam Registration</display-name>
  
  <module>
    <web>
      <web-uri>jboss-seam-registration.war</web-uri>
      <context-root>/seam-registration</context-root>
    </web>
  </module>
  <module>
    <ejb>jboss-seam-registration.jar</ejb>
  </module>
  <module>
    <ejb>jboss-seam.jar</ejb>
  </module>
  <module>
    <java>jboss-el.jar</java>
  </module>

</application>
Copy to Clipboard Toggle word wrap
このデプロイメント記述子はエンタープライズアーカイブのモジュールとリンクし、Web アプリケーションをコンテキストルート /seam-registration にバインドします。
これでアプリケーションにあるすべてのファイルを見てきました。
トップに戻る
Red Hat logoGithubredditYoutubeTwitter

詳細情報

試用、購入および販売

コミュニティー

Red Hat ドキュメントについて

Red Hat をお使いのお客様が、信頼できるコンテンツが含まれている製品やサービスを活用することで、イノベーションを行い、目標を達成できるようにします。 最新の更新を見る.

多様性を受け入れるオープンソースの強化

Red Hat では、コード、ドキュメント、Web プロパティーにおける配慮に欠ける用語の置き換えに取り組んでいます。このような変更は、段階的に実施される予定です。詳細情報: Red Hat ブログ.

会社概要

Red Hat は、企業がコアとなるデータセンターからネットワークエッジに至るまで、各種プラットフォームや環境全体で作業を簡素化できるように、強化されたソリューションを提供しています。

Theme

© 2025 Red Hat