---
title: Java EE 6 ハンズオンラボでJavaEE6を始めよう！(JBoss Forge付き) javaee glassfishjp
tags: []
categories: ["Programming", "Java", "JavaEE6", "AdventCalendar", "2012"]
date: 2012-11-20T17:17:57Z
updated: 2012-11-30T19:41:04Z
---

[JavaEE Advent Calendar 2012][1] 1日目の記事です。

### Java EE6 ハンズオンラボ

Oracleの[@arungupta][2]さんが公開している[JavaEE6ハンズオンラボ][3]はご存知でしょうか？
このハンズオンでは簡単なアプリケーションを作成することでJavaEE6の主要技術を一通り学ぶことができます。
扱っている技術は

* JPA 2 (MetaModelを使ったCriteriaQuery含む)
* Sevlet 3
* EJB 3.1 (@Schedule含む)
* JSF 2 (Ajax含む)
* JAX-RS
* CDI (Interceptor含む)
* Bean Validation

です。46ページのドキュメントですが要領よく、かなり網羅されています。

これからJavaEE6を始める人の最初の一歩にぴったりではないでしょうか。


<a href="http://www.amazon.co.jp/exec/obidos/ASIN/4798124605/ikam-22/ref=nosim/" name="amazletlink" target="_blank"><img src="http://ecx.images-amazon.com/images/I/517MsPjZfvL._SL160_.jpg" alt="Beginning Java EE 6 GlassFish 3で始めるエンタープライズJava (Programmer’s SELECTION)" style="border: none;" /></a>

金魚本についている付録のハンズオンはこの資料の前のバージョンの翻訳です(あれを書いたのも実は自分なのですが。。色々すいません)。

そして今回のバージョンの資料は細々と翻訳しています。
[https://github.com/making/javaee6-hol-glassfish-doc][4]

翻訳バージョンは[https://javaee6-hol-glassfish-doc.readthedocs.org/][5]から参照可能です(随時更新中)

訳がいまいちなところも多々あるので、翻訳に協力してくれる方はpull requestください！
よろしくお願いします！！


### JBoss Forgeでチュートリアルを進めてみる

ではこのチュートリアルを[JBoss Forge][6]で作ってみましょう。
本家チュートリアルではNetBeansを使ってJavaEE6アプリケーションを作成していますが、
折角なのであえてJBoss Forgeでもやってみます。

元々次の回に書くつもりでしたが、JavaEE Advent Calendarが埋まっちゃったので。。

#### JBoss Forgeって何？
JBoss ForgeはJava EE用のRADツールで、プロジェクト(+ソース)雛形生成ツールという色が強いです。コマンドラインでMavenベースドなプロジェクトを構築して、ソースコードを生成していきます。
JBossプロダクトですが、APサーバーはJBoss ASに限定しているわけではなく、Glass Fishでも全然OKです。
似たようなプロジェクトで[Spring Roo][7]がありますが、Rooは生成されたコードがAspectJの黒魔術すぎて、生成した後実際にどうプロジェクトを進めて良いかわからん！というのに対して、Forgeはplainなソースコードを吐いてくれるので、出力したあと自分で作り込んでいくというのが容易です。

#### JBoss Forgeをインストール
Macユーザーはbrewでインストールできます。非Macユーザーは自分で調べてください。Mac買えや。

    $ brew install jboss-forge
    ==> Downloading https://repository.jboss.org/nexus/service/local/artifact/maven/redirect?r=releases&g=org.jboss.forge&a=forge-distribution&v=1.1.1.Final&e=zi
    ######################################################################## 100.0%
    /usr/local/Cellar/jboss-forge/1.1.1.Final: 209 files, 29M, built in 107 seconds

#### JBoss Forgeを実行
`forge`コマンドで起動します。環境変数`JAVA_HOME`が設定されている必要があります。
Macユーザーは

    $ export JAVA_HOME=/Library/Java/JavaVirtualMachines/1.7.0.jdk/Contents/Home/ 

な感じ。

    $ forge
    Using Forge at /usr/local/Cellar/jboss-forge/1.1.1.Final/libexec
        _____                    
       |  ___|__  _ __ __ _  ___ 
       | |_ / _ \| `__/ _` |/ _ \  \\
       |  _| (_) | | | (_| |  __/  //
       |_|  \___/|_|  \__, |\___| 
                       |___/      
    
    JBoss Forge, version [ 1.1.1.Final ] - JBoss, by Red Hat, Inc. [ http://jboss.org/forge ]

#### プロジェクト作成

`new-project`コマンドでプロジェクトを作成します。名前とトップレベルのパッケージを指定します(Rooとそっくり)。チュートリアルにしたがってプロジェクト名を"JavaEE6SampleApp"、トップレベルのパッケージを"org.glassfish.samples"

    [no project] forge $ new-project --named JavaEE6SampleApp --topLevelPackage org.glassfish.samples
     ? Use [/Users/maki/forge/JavaEE6SampleApp] as project directory? [Y/n] 
    ***SUCCESS*** Created project [JavaEE6SampleApp] in new working directory [/Users/maki/forge/JavaEE6SampleApp]
    Wrote /Users/maki/forge/JavaEE6SampleApp
    Wrote /Users/maki/forge/JavaEE6SampleApp/pom.xml
    Wrote /Users/maki/forge/JavaEE6SampleApp/src/main/java
    Wrote /Users/maki/forge/JavaEE6SampleApp/src/test/java
    Wrote /Users/maki/forge/JavaEE6SampleApp/src/main/resources
    Wrote /Users/maki/forge/JavaEE6SampleApp/src/test/resources
    Wrote /Users/maki/forge/JavaEE6SampleApp/src/main/java/org/glassfish/samples

#### Scaffoldの設定
RADツール定番のScaffoldです。まずはセットアップでViewテクノロジーを選択します。当然JSFを指定。`scaffold`コマンドを実行します。設定はデフォルトでいいのでEnterを押しまくってください。

    [JavaEE6SampleApp] JavaEE6SampleApp $ scaffold setup --scaffoldType faces
     ? Scaffold provider [faces] is not installed. Install it? [Y/n] 
     ? Facet [forge.maven.WebResourceFacet] requires packaging type(s) [war], but is currently [jar]. Update packaging? (Note: this could deactivate other plugins in your project.) [Y/n] 
    ***SUCCESS*** Installed [forge.maven.WebResourceFacet] successfully.
    Use which version of 'jboss-javaee-6.0' ?
    
      1 - [org.jboss.spec:jboss-javaee-6.0:pom::1.0.0.Beta4]
      2 - [org.jboss.spec:jboss-javaee-6.0:pom::1.0.0.Beta5]
      3 - [org.jboss.spec:jboss-javaee-6.0:pom::1.0.0.Beta6]
      4 - [org.jboss.spec:jboss-javaee-6.0:pom::1.0.0.Beta7]
      5 - [org.jboss.spec:jboss-javaee-6.0:pom::1.0.0.CR1]
      6 - [org.jboss.spec:jboss-javaee-6.0:pom::1.0.0.Final]
      7 - [org.jboss.spec:jboss-javaee-6.0:pom::2.0.0.Beta1]
      8 - [org.jboss.spec:jboss-javaee-6.0:pom::2.0.0.CR1]
      9 - [org.jboss.spec:jboss-javaee-6.0:pom::2.0.0.Final]
      10 - [org.jboss.spec:jboss-javaee-6.0:pom::2.1.0.Beta1]
      11 - [org.jboss.spec:jboss-javaee-6.0:pom::3.0.0.Beta1]
      12 - [org.jboss.spec:jboss-javaee-6.0:pom::3.0.0.Final]
      13 - [org.jboss.spec:jboss-javaee-6.0:pom::3.0.1.Final]*
    
     ? Choose an option by typing the number of the selection [*-default]  [0] 
    ***SUCCESS*** Installed [forge.spec.jpa] successfully.
    ***SUCCESS*** Installed [forge.spec.ejb] successfully.
    ***SUCCESS*** Installed [forge.spec.cdi] successfully.
    ***SUCCESS*** Installed [forge.spec.servlet] successfully.
    ***SUCCESS*** Installed [forge.spec.jsf.api] successfully.
    ***SUCCESS*** Installed [faces] successfully.
     ? Create scaffold in which sub-directory of web-root? (e.g. http://localhost:8080/JavaEE6SampleApp/DIR) [/] 
    Wrote /Users/maki/forge/JavaEE6SampleApp/src/main/webapp
    Wrote /Users/maki/forge/JavaEE6SampleApp/pom.xml
    Wrote /Users/maki/forge/JavaEE6SampleApp/src/main/resources/META-INF/persistence.xml
    Wrote /Users/maki/forge/JavaEE6SampleApp/src/main/webapp/WEB-INF/beans.xml
    Wrote /Users/maki/forge/JavaEE6SampleApp/src/main/webapp/WEB-INF/faces-config.xml
    Wrote /Users/maki/forge/JavaEE6SampleApp/src/main/webapp/favicon.ico
    Wrote /Users/maki/forge/JavaEE6SampleApp/src/main/webapp/resources/scaffold/paginator.xhtml
    Wrote /Users/maki/forge/JavaEE6SampleApp/src/main/webapp/resources/scaffold/pageTemplate.xhtml
    Wrote /Users/maki/forge/JavaEE6SampleApp/src/main/webapp/index.html
    Wrote /Users/maki/forge/JavaEE6SampleApp/src/main/webapp/index.xhtml
    Wrote /Users/maki/forge/JavaEE6SampleApp/src/main/webapp/error.xhtml
    Wrote /Users/maki/forge/JavaEE6SampleApp/src/main/webapp/resources/add.png
    Wrote /Users/maki/forge/JavaEE6SampleApp/src/main/webapp/resources/bootstrap.css
    Wrote /Users/maki/forge/JavaEE6SampleApp/src/main/webapp/resources/false.png
    Wrote /Users/maki/forge/JavaEE6SampleApp/src/main/webapp/resources/favicon.ico
    Wrote /Users/maki/forge/JavaEE6SampleApp/src/main/webapp/resources/forge-logo.png
    Wrote /Users/maki/forge/JavaEE6SampleApp/src/main/webapp/resources/forge-style.css
    Wrote /Users/maki/forge/JavaEE6SampleApp/src/main/webapp/resources/remove.png
    Wrote /Users/maki/forge/JavaEE6SampleApp/src/main/webapp/resources/search.png
    Wrote /Users/maki/forge/JavaEE6SampleApp/src/main/webapp/resources/true.png
    Wrote /Users/maki/forge/JavaEE6SampleApp/src/main/webapp/resources/jboss-community.png
    Wrote /Users/maki/forge/JavaEE6SampleApp/src/main/webapp/WEB-INF/web.xml

実はデフォルトでJSFしか選べません。プラグインをインストールすることでViewを追加することが出来ます。なんとSpring MVC版も作れたりします!

#### JPAの設定
JPAの設定をします。Hibernate、JBoss ASを使わず、あえてEclipseLink、GlassFishを選択します。データソースのJNDI名もチュートリアルにあわせてjdbc/sampleに。

    [JavaEE6SampleApp] JavaEE6SampleApp $ persistence setup --provider ECLIPSELINK --container GLASSFISH_3 --jndiDataSource jdbc/sample
    ***INFO*** Setting transaction-type="JTA"
    ***INFO*** Overriding example datasource with [jdbc/sample]
     ? Do you want to install a JPA 2 metamodel generator? [y/N] 
     ? The JPA provider [ECLIPSELINK], also supplies extended APIs. Install these as well? [y/N] 
    ***SUCCESS*** Persistence (JPA) is installed.
    Wrote /Users/maki/forge/JavaEE6SampleApp/src/main/resources/META-INF/persistence.xml

次のようなpersistence.xmlが出力されます。


    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
      <persistence-unit name="forge-default" transaction-type="JTA">
        <description>Forge Persistence Unit</description>
        <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
        <jta-data-source>jdbc/sample</jta-data-source>
        <exclude-unlisted-classes>false</exclude-unlisted-classes>
        <properties>
          <property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
        </properties>
      </persistence-unit>
    </persistence>

#### Entityを作成
チュートリアルでは既存でDBテーブルからリバースエンジニアリングでEntityを生成していますが、今回はまずは先にEntityを作成してみます。連絡先Eメールアドレスと名前を持ったContactエンティティを作成してみます。パッケージ名は`org.glassfish.samples.entities`で。


    [JavaEE6SampleApp] JavaEE6SampleApp $ entity --named Contact --package org.glassfish.samples.entities --idStrategy AUTO 
    Created @Entity [org.glassfish.samples.entities.Contact]
    Picked up type <JavaResource>: org.glassfish.samples.entities.Contact
    Wrote /Users/maki/forge/JavaEE6SampleApp/src/main/java/org/glassfish/samples/entities/Contact.java
    [JavaEE6SampleApp] Contact.java $ field string --named email
    Added field to org.glassfish.samples.entities.Contact: @Column private String email;
    
    Wrote /Users/maki/forge/JavaEE6SampleApp/src/main/java/org/glassfish/samples/entities/Contact.java
    [JavaEE6SampleApp] Contact.java $ field string --named name
    Added field to org.glassfish.samples.entities.Contact: @Column private String name;
    
    Wrote /Users/maki/forge/JavaEE6SampleApp/src/main/java/org/glassfish/samples/entities/Contact.java

`ls`コマンドでフィールド、メソッド一覧を表示できます。id、versionは勝手に付与されます。

    [JavaEE6SampleApp] Contact.java $ ls
    
    [fields]
    private::Long::id;             private::String::email;        private::String::name;
    private::int::version;         
    
    [methods]
    public::equals(Object that)::boolean                   public::getEmail()::String
    public::getId()::Long                                  public::getName()::String
    public::getVersion()::int                              public::hashCode()::int
    public::setEmail(final String email)::void             public::setId(final Long id)::void
    public::setName(final String name)::void               public::setVersion(final int version)::void
    public::toString()::String  

実際には次のようなソースが出力されています。
  

    package org.glassfish.samples.entities;
    
    import javax.persistence.Entity;
    import java.io.Serializable;
    import javax.persistence.Id;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Column;
    import javax.persistence.Version;
    import java.lang.Override;
    
    @Entity
    public class Contact implements Serializable
    {
    
       @Id
       private @GeneratedValue(strategy = GenerationType.AUTO)
       @Column(name = "id", updatable = false, nullable = false)
       Long id = null;
       @Version
       private @Column(name = "version")
       int version = 0;
    
       @Column
       private String email;
    
       @Column
       private String name;
    
       public Long getId()
       {
          return this.id;
       }
    
       public void setId(final Long id)
       {
          this.id = id;
       }
    
       public int getVersion()
       {
          return this.version;
       }
    
       public void setVersion(final int version)
       {
          this.version = version;
       }
    
       @Override
       public boolean equals(Object that)
       {
          if (this == that)
          {
             return true;
          }
          if (that == null)
          {
             return false;
          }
          if (getClass() != that.getClass())
          {
             return false;
          }
          if (id != null)
          {
             return id.equals(((Contact) that).id);
          }
          return super.equals(that);
       }
    
       @Override
       public int hashCode()
       {
          if (id != null)
          {
             return id.hashCode();
          }
          return super.hashCode();
       }
    
       public String getEmail()
       {
          return this.email;
       }
    
       public void setEmail(final String email)
       {
          this.email = email;
       }
    
       public String getName()
       {
          return this.name;
       }
    
       public void setName(final String name)
       {
          this.name = name;
       }
    
       public String toString()
       {
          String result = "";
          if (email != null && !email.trim().isEmpty())
             result += email;
          if (name != null && !name.trim().isEmpty())
             result += " " + name;
          return result;
       }
    }

#### EntityからScaffold生成
さっきセットアップしたScaffoldを実際に生成しています。



    [JavaEE6SampleApp] Contact.java $ scaffold from-entity
    ***INFO*** Using currently installed scaffold [faces]
     ? [/Users/maki/forge/JavaEE6SampleApp/src/main/webapp/resources/scaffold/pageTemplate.xhtml] File exists, overwrite? [Y/n] 
    ***SUCCESS*** Generated UI for [org.glassfish.samples.entities.Contact]
    Wrote /Users/maki/forge/JavaEE6SampleApp/src/main/java/org/glassfish/samples/view/ContactBean.java
    Wrote /Users/maki/forge/JavaEE6SampleApp/src/main/webapp/contact/create.xhtml
    Wrote /Users/maki/forge/JavaEE6SampleApp/src/main/webapp/contact/view.xhtml
    Wrote /Users/maki/forge/JavaEE6SampleApp/src/main/webapp/contact/search.xhtml
    Wrote /Users/maki/forge/JavaEE6SampleApp/src/main/webapp/resources/scaffold/pageTemplate.xhtml
    Wrote /Users/maki/forge/JavaEE6SampleApp/src/main/java/org/glassfish/samples/view/ViewUtils.java
    Wrote /Users/maki/forge/JavaEE6SampleApp/src/main/webapp/WEB-INF/classes/META-INF/forge.taglib.xml
    Wrote /Users/maki/forge/JavaEE6SampleApp/src/main/java/org/glassfish/samples/entities/Contact.java

パッケージ名を指定しないとviewパッケージに出力されます。まあいいか。

#### NetBeanでプロジェクトを開く

ForgeでできたプロジェクトはMavenプロジェクトなのでNetBeansでそのまま開けます。開く前にJTAのセットアップをしておきます。これがないとNetBeansでエラーになります。

    [JavaEE6SampleApp] Contact.java $ jta setup 
    ***SUCCESS*** Installed [forge.spec.jta] successfully.
    ***SUCCESS*** Java Transaction API (JTA) is installed.
    Wrote /Users/maki/forge/JavaEE6SampleApp/pom.xml

NetBeansを開いて「プロジェクトを開く」で"JavaEE6SampleApp"を選択し開きます。

<a href='/api/v1/files/00074/ss01.png'><img src='/api/v1/files/00074/ss01.png' /></a>

こんな感じのプロジェクトになります。

<a href='/api/v1/files/00075/ss02.png'><img src='/api/v1/files/00075/ss02.png' /></a>

一時的にsrc/main/resources/META-INF/persistence.xmlの"eclipselink.ddl-generation"の値を"create-tables"に変えておきます。

    <property name="eclipselink.ddl-generation" value="create-tables"/>

GlassFishを起動した後、プロジェクト名を右クリックして「実行」をクリック。サーバーを選択。

<a href='/api/v1/files/00076/ss03.png'><img src='/api/v1/files/00076/ss03.png' /></a>

ブラウザが立ち上がり次のような画面が表示されます。

<a href='/api/v1/files/00077/ss04.png'><img src='/api/v1/files/00077/ss04.png' /></a>

左側の"Contact"をクリックするとContactエンティティのCRUD画面へ遷移します。

<a href='/api/v1/files/00078/ss05.png'><img src='/api/v1/files/00078/ss05.png' /></a>

#### 既存のテーブルからEntityをリバースエンジニアリングする

チュートリアル同様、APPデスキーマのテーブルからEntityを自動生成してみます。
実はリバースエンジニアリング機能は標準ではなくて、hibernate-toolsプラグインをインストールする必要があります。

    [JavaEE6SampleApp] Contact.java $ forge install-plugin hibernate-tools 

NetBeansで立ち上げているDerbyに接続して自動生成させます。derbyclient.jarの位置は適宜修正してください。

    [JavaEE6SampleApp] entities $ generate-entities --datasource jdbc/sample --url jdbc:derby://localhost:1527/sample --schema APP --user app --dialect org.hibernate.dialect.DerbyDialect --driver org.apache.derby.jdbc.ClientDriver --pathToDriver /Applications/NetBeans/glassfish-3.1.2.2/javadb/lib/derbyclient.jar --entityPackage org.glassfish.samples.entities
     ? Enter the password for JDBC connection. ***
    Found 9 tables in datasource
    Generated java at /Users/maki/forge/JavaEE6SampleApp/src/main/java/org/glassfish/samples/entities/Customer.java
    Generated java at /Users/maki/forge/JavaEE6SampleApp/src/main/java/org/glassfish/samples/entities/Sequence.java
    Generated java at /Users/maki/forge/JavaEE6SampleApp/src/main/java/org/glassfish/samples/entities/Product.java
    Generated java at /Users/maki/forge/JavaEE6SampleApp/src/main/java/org/glassfish/samples/entities/Manufacturer.java
    Generated java at /Users/maki/forge/JavaEE6SampleApp/src/main/java/org/glassfish/samples/entities/PurchaseOrder.java
    Generated java at /Users/maki/forge/JavaEE6SampleApp/src/main/java/org/glassfish/samples/entities/MicroMarket.java
    Generated java at /Users/maki/forge/JavaEE6SampleApp/src/main/java/org/glassfish/samples/entities/ProductCode.java
    Generated java at /Users/maki/forge/JavaEE6SampleApp/src/main/java/org/glassfish/samples/entities/Contact.java
    Generated java at /Users/maki/forge/JavaEE6SampleApp/src/main/java/org/glassfish/samples/entities/DiscountCode.java
    Generated 9 java files.

エンティティが生成されました。"eclipselink.ddl-generation"を"none"に変更します。

      <property name="eclipselink.ddl-generation" value="none"/>

そしてScaffoldを再実行。

    [JavaEE6SampleApp] entities $ scaffold from-entity org.glassfish.samples.entities.* --overwrite 
    ***INFO*** Using currently installed scaffold [faces]
    ***SUCCESS*** Generated UI for [org.glassfish.samples.entities.Contact]
    ***SUCCESS*** Generated UI for [org.glassfish.samples.entities.Customer]
    ***SUCCESS*** Generated UI for [org.glassfish.samples.entities.DiscountCode]
    ***SUCCESS*** Generated UI for [org.glassfish.samples.entities.Manufacturer]
    ***SUCCESS*** Generated UI for [org.glassfish.samples.entities.MicroMarket]
    ***SUCCESS*** Generated UI for [org.glassfish.samples.entities.Product]
    ***SUCCESS*** Generated UI for [org.glassfish.samples.entities.ProductCode]
    ***SUCCESS*** Generated UI for [org.glassfish.samples.entities.PurchaseOrder]
    ***SUCCESS*** Generated UI for [org.glassfish.samples.entities.Sequence]
    Wrote (略..)

再実行すると次のようにエンティティの選択肢が増えます。

<a href='/api/v1/files/00079/ss06.png'><img src='/api/v1/files/00079/ss06.png' /></a>
<a href='/api/v1/files/00080/ss07.png'><img src='/api/v1/files/00080/ss07.png' /></a>

さてここからチュートリアルではServletを作ったり、EJBを作ったりするわけですが、
本記事ではこの辺で終了しておきます。。というかNetBeansで直接作っちゃってOKです。
(ちなみに↑くらいのScaffoldならNetBeans単体で実現できます。。出力されるManagedBeanのソースもあまり奇麗でない。。)

src/main/webapp/resources/scaffold/pageTemplate.xhtmlにFaceletsのテンプレートができているので、
これをベースに新規ページを作っていくのが良いのではないでしょうか。

(ちなみに次のGlassFish勉強会でもこのネタ発表します。。ネタ少なくてすいません)

2日目は[@megascus][8]さんお願いします！


  [1]: http://atnd.org/events/33783
  [2]: https://twitter.com/arungupta
  [3]: https://blogs.oracle.com/arungupta/resource/javaee6-hol-glassfish.pdf
  [4]: https://github.com/making/javaee6-hol-glassfish-doc
  [5]: https://javaee6-hol-glassfish-doc.readthedocs.org/
  [6]: http://forge.jboss.org/
  [7]: http://www.springsource.org/spring-roo
  [8]: https://twitter.com/megascus
