nekop's blog

OpenShift / JBoss / WildFly / Infinispanの中の人 http://twitter.com/nekop

JBoss Forge 1.0.0.Beta4を試す

JBoss Advent Calendar 2011の20日目のエントリです。JBoss Forge 1.0.0.Beta4がリリースされたので試してみます。

JBoss Forgeは超速Java EEアプリケーション開発を実現するためのツールです。元々Seam Forgeという名前でSeamのサブプロジェクトとして開発されたのですが、Seamへの依存は無く、JBossのプロジェクトとして独立しました。

さて、起動してみましょう。zipダウンロードして展開してJBOSS_HOMEを指定して起動します。

$ cd ~/tmp
$ wget "https://repository.jboss.org/nexus/service/local/artifact/maven/redirect?r=releases&g=org.jboss.forge&a=forge-distribution&v=1.0.0.Beta4&e=zip"
$ unzip forge-distribution-1.0.0.Beta4.zip
$ JBOSS_HOME=/home/nekop/jboss710b1b ./forge-distribution-1.0.0.Beta4/bin/forge
Using Forge at /home/nekop/usr/local/forge-distribution-1.0.0.Beta4
    _____                    
   |  ___|__  _ __ __ _  ___ 
   | |_ / _ \| `__/ _` |/ _ \  \\
   |  _| (_) | | | (_| |  __/  //
   |_|  \___/|_|  \__, |\___| 
                   |___/      
 
[no project] tmp $ 

Forgeはおおざっぱに以下の流れで利用します。

Forgeを使ってプロジェクトを作成すると、そのプロジェクトへサポートされるテクノロジを自由に追加できます。例えば以下のように実行すると、現在のプロジェクトにJPAのサポートが追加されます。

$ persistence setup --provider HIBERNATE --container JBOSS_AS7 ;

コマンド一覧はlist-commandsコマンドで出力されます。

$ list-commands

さて、GitHub上のショーケースのサンプルを実行してみます。名前とパッケージ名は適当に"foo"と入れました。

[no project] tmp $ run-url https://raw.github.com/forge/core/master/showcase/posale.fsh
Wrote /tmp/tempc726d6b63a8d405e87f1106dcf2880bf
 ? [named=The name of the new project (of type java.lang.String)]: foo
 ? [topLevelPackage=The top-level java package for the project [e.g: "com.example.project"]  (of type java.lang.String)]: foo
 ? Use [/home/nekop/tmp/foo] as project directory? [Y/n] 
***SUCCESS*** Created project [foo] in new working directory [/home/nekop/tmp/foo]
Wrote /home/nekop/tmp/foo
Wrote /home/nekop/tmp/foo/pom.xml
Wrote /home/nekop/tmp/foo/src/main/java
Wrote /home/nekop/tmp/foo/src/test/java
Wrote /home/nekop/tmp/foo/src/main/resources
Wrote /home/nekop/tmp/foo/src/test/resources
Wrote /home/nekop/tmp/foo/src/main/resources/META-INF/forge.xml
 ? 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.
Warning:  The encoding 'UTF-8' is not supported by the Java runtime.
***SUCCESS*** Installed [forge.spec.jpa] successfully.
***SUCCESS*** Installed [forge.spec.ejb] successfully.
***SUCCESS*** Installed [forge.spec.cdi] successfully.
Warning:  The encoding 'UTF-8' is not supported by the Java runtime.
***SUCCESS*** Installed [forge.spec.servlet] successfully.
***SUCCESS*** Installed [forge.spec.jsf] successfully.
***SUCCESS*** Installed [faces] successfully.
Warning:  The encoding 'UTF-8' is not supported by the Java runtime.
Warning:  The encoding 'UTF-8' is not supported by the Java runtime.
Wrote /home/nekop/tmp/foo/src/main/webapp
Wrote /home/nekop/tmp/foo/pom.xml
Wrote /home/nekop/tmp/foo/src/main/resources/META-INF/persistence.xml
Wrote /home/nekop/tmp/foo/src/main/webapp/WEB-INF/beans.xml
Wrote /home/nekop/tmp/foo/src/main/webapp/WEB-INF/web.xml
Wrote /home/nekop/tmp/foo/src/main/webapp/WEB-INF/faces-config.xml
Wrote /home/nekop/tmp/foo/src/main/webapp/favicon.ico
Wrote /home/nekop/tmp/foo/src/main/webapp/resources/scaffold/paginator.xhtml
Wrote /home/nekop/tmp/foo/src/main/webapp/resources/scaffold/page.xhtml
Wrote /home/nekop/tmp/foo/src/main/webapp/index.html
Wrote /home/nekop/tmp/foo/src/main/webapp/index.xhtml
Wrote /home/nekop/tmp/foo/src/main/webapp/error.xhtml
Wrote /home/nekop/tmp/foo/src/main/webapp/resources/background.gif
Wrote /home/nekop/tmp/foo/src/main/webapp/resources/favicon.ico
Wrote /home/nekop/tmp/foo/src/main/webapp/resources/forge-logo.png
Wrote /home/nekop/tmp/foo/src/main/webapp/resources/forge-style.css
Wrote /home/nekop/tmp/foo/src/main/webapp/resources/jboss-community.png
Wrote /home/nekop/tmp/foo/src/main/webapp/resources/search.png
***INFO*** Setting transaction-type="JTA"
***INFO*** Using example data source [java:jboss/datasources/ExampleDS]
Warning:  The encoding 'UTF-8' is not supported by the Java runtime.
 ? The JPA provider [HIBERNATE], also supplies extended APIs. Install these as well? [y/N] 
***SUCCESS*** Persistence (JPA) is installed.
Wrote /home/nekop/tmp/foo/src/main/resources/META-INF/persistence.xml
Created @Entity [foo.domain.Customer]
Picked up type <JavaResource>: foo.domain.Customer
Wrote /home/nekop/tmp/foo/src/main/java/foo/domain/Customer.java
Added field to foo.domain.Customer: @Column private String firstName;

Wrote /home/nekop/tmp/foo/src/main/java/foo/domain/Customer.java
Added field to foo.domain.Customer: @Column private String lastName;

Wrote /home/nekop/tmp/foo/src/main/java/foo/domain/Customer.java
Added field to foo.domain.Customer: private @Temporal(TemporalType.DATE) Date birthDate;

Wrote /home/nekop/tmp/foo/src/main/java/foo/domain/Customer.java
Created @Entity [foo.domain.Item]
Picked up type <JavaResource>: foo.domain.Item
Wrote /home/nekop/tmp/foo/src/main/java/foo/domain/Item.java
Added field to foo.domain.Item: @Column private String name;

Wrote /home/nekop/tmp/foo/src/main/java/foo/domain/Item.java
Added field to foo.domain.Item: @Column private Double price;

Wrote /home/nekop/tmp/foo/src/main/java/foo/domain/Item.java
Added field to foo.domain.Item: @Column private int stock;

Wrote /home/nekop/tmp/foo/src/main/java/foo/domain/Item.java
Created @Entity [foo.domain.ProductOrder]
Picked up type <JavaResource>: foo.domain.ProductOrder
Wrote /home/nekop/tmp/foo/src/main/java/foo/domain/ProductOrder.java
Wrote /home/nekop/tmp/foo/src/main/java/foo/domain/Customer.java
Wrote /home/nekop/tmp/foo/src/main/java/foo/domain/ProductOrder.java
Created @Entity [foo.domain.Profile]
Picked up type <JavaResource>: foo.domain.Profile
Wrote /home/nekop/tmp/foo/src/main/java/foo/domain/Profile.java
Added field to foo.domain.Profile: @Column private String bio;

Wrote /home/nekop/tmp/foo/src/main/java/foo/domain/Profile.java
Added field to foo.domain.Profile: @Column private String preferredName;

Wrote /home/nekop/tmp/foo/src/main/java/foo/domain/Profile.java
Added field to foo.domain.Profile: @Column private String notes;

Wrote /home/nekop/tmp/foo/src/main/java/foo/domain/Profile.java
Created @Entity [foo.domain.Address]
Picked up type <JavaResource>: foo.domain.Address
Wrote /home/nekop/tmp/foo/src/main/java/foo/domain/Address.java
Added field to foo.domain.Address: @Column private String street;

Wrote /home/nekop/tmp/foo/src/main/java/foo/domain/Address.java
Added field to foo.domain.Address: @Column private String city;

Wrote /home/nekop/tmp/foo/src/main/java/foo/domain/Address.java
Created @Entity [foo.domain.ZipCode]
Picked up type <JavaResource>: foo.domain.ZipCode
Wrote /home/nekop/tmp/foo/src/main/java/foo/domain/ZipCode.java
Added field to foo.domain.ZipCode: @Column private int code;

Wrote /home/nekop/tmp/foo/src/main/java/foo/domain/ZipCode.java
Wrote /home/nekop/tmp/foo/src/main/java/foo/domain/Address.java
Wrote /home/nekop/tmp/foo/src/main/java/foo/domain/Customer.java
Added field to foo.domain.Customer: @OneToOne private Profile profile;

Wrote /home/nekop/tmp/foo/src/main/java/foo/domain/Customer.java
Wrote /home/nekop/tmp/foo/src/main/java/foo/domain/ProductOrder.java
Wrote /home/nekop/tmp/foo/src/main/java/foo/domain/ProductOrder.java
***SUCCESS*** Generated UI for [foo.domain.Address]
***SUCCESS*** Generated UI for [foo.domain.ZipCode]
***SUCCESS*** Generated UI for [foo.domain.Profile]
***SUCCESS*** Generated UI for [foo.domain.Item]
***SUCCESS*** Generated UI for [foo.domain.ProductOrder]
***SUCCESS*** Generated UI for [foo.domain.Customer]
Wrote /home/nekop/tmp/foo/src/main/java/foo/view/AddressBean.java
Wrote /home/nekop/tmp/foo/src/main/webapp/scaffold/address/create.xhtml
Wrote /home/nekop/tmp/foo/src/main/webapp/scaffold/address/view.xhtml
Wrote /home/nekop/tmp/foo/src/main/webapp/scaffold/address/search.xhtml
Wrote /home/nekop/tmp/foo/src/main/webapp/resources/scaffold/page.xhtml
Wrote /home/nekop/tmp/foo/src/main/java/foo/view/ViewUtils.java
Wrote /home/nekop/tmp/foo/src/main/webapp/WEB-INF/classes/META-INF/forge.taglib.xml
Wrote /home/nekop/tmp/foo/src/main/java/foo/domain/Address.java
Wrote /home/nekop/tmp/foo/src/main/java/foo/view/ZipCodeBean.java
Wrote /home/nekop/tmp/foo/src/main/webapp/scaffold/zipCode/create.xhtml
Wrote /home/nekop/tmp/foo/src/main/webapp/scaffold/zipCode/view.xhtml
Wrote /home/nekop/tmp/foo/src/main/webapp/scaffold/zipCode/search.xhtml
Wrote /home/nekop/tmp/foo/src/main/java/foo/domain/ZipCode.java
Wrote /home/nekop/tmp/foo/src/main/java/foo/view/ProfileBean.java
Wrote /home/nekop/tmp/foo/src/main/webapp/scaffold/profile/create.xhtml
Wrote /home/nekop/tmp/foo/src/main/webapp/scaffold/profile/view.xhtml
Wrote /home/nekop/tmp/foo/src/main/webapp/scaffold/profile/search.xhtml
Wrote /home/nekop/tmp/foo/src/main/java/foo/domain/Profile.java
Wrote /home/nekop/tmp/foo/src/main/java/foo/view/ItemBean.java
Wrote /home/nekop/tmp/foo/src/main/webapp/scaffold/item/create.xhtml
Wrote /home/nekop/tmp/foo/src/main/webapp/scaffold/item/view.xhtml
Wrote /home/nekop/tmp/foo/src/main/webapp/scaffold/item/search.xhtml
Wrote /home/nekop/tmp/foo/src/main/java/foo/domain/Item.java
Wrote /home/nekop/tmp/foo/src/main/java/foo/view/ProductOrderBean.java
Wrote /home/nekop/tmp/foo/src/main/webapp/scaffold/productOrder/create.xhtml
Wrote /home/nekop/tmp/foo/src/main/webapp/scaffold/productOrder/view.xhtml
Wrote /home/nekop/tmp/foo/src/main/webapp/scaffold/productOrder/search.xhtml
Wrote /home/nekop/tmp/foo/src/main/java/foo/domain/ProductOrder.java
Wrote /home/nekop/tmp/foo/src/main/java/foo/view/CustomerBean.java
Wrote /home/nekop/tmp/foo/src/main/webapp/scaffold/customer/create.xhtml
Wrote /home/nekop/tmp/foo/src/main/webapp/scaffold/customer/view.xhtml
Wrote /home/nekop/tmp/foo/src/main/webapp/scaffold/customer/search.xhtml
Wrote /home/nekop/tmp/foo/src/main/java/foo/domain/Customer.java
[INFO] Scanning for projects...
[WARNING] 
[WARNING] Some problems were encountered while building the effective model for foo:foo:war:1.0.0-SNAPSHOT
[WARNING] 'build.plugins.plugin.version' for org.apache.maven.plugins:maven-war-plugin is missing. @ line 74, column 15
[WARNING] 
[WARNING] It is highly recommended to fix these problems because they threaten the stability of your build.
[WARNING] 
[WARNING] For this reason, future Maven versions might no longer support building such malformed projects.
[WARNING] 
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building foo 1.0.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- maven-resources-plugin:2.4.3:resources (default-resources) @ foo ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 2 resources
[INFO] 
[INFO] --- maven-compiler-plugin:2.3.2:compile (default-compile) @ foo ---
[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
[INFO] Compiling 13 source files to /home/nekop/tmp/foo/target/classes
[INFO] 
[INFO] --- maven-resources-plugin:2.4.3:testResources (default-testResources) @ foo ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 0 resource
[INFO] 
[INFO] --- maven-compiler-plugin:2.3.2:testCompile (default-testCompile) @ foo ---
[INFO] Nothing to compile - all classes are up to date
[INFO] 
[INFO] --- maven-surefire-plugin:2.7.2:test (default-test) @ foo ---
[INFO] Surefire report directory: /home/nekop/tmp/foo/target/surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
There are no tests to run.

Results :

Tests run: 0, Failures: 0, Errors: 0, Skipped: 0

[INFO] 
[INFO] --- maven-war-plugin:2.1.1:war (default-war) @ foo ---
[INFO] Packaging webapp
[INFO] Assembling webapp [foo] in [/home/nekop/tmp/foo/target/foo]
[INFO] Processing war project
[INFO] Copying webapp resources [/home/nekop/tmp/foo/src/main/webapp]
[INFO] Webapp assembled in [27 msecs]
[INFO] Building war: /home/nekop/tmp/foo/target/foo.war
[INFO] WEB-INF/web.xml already added, skipping
[INFO] 
[INFO] --- maven-install-plugin:2.3.1:install (default-install) @ foo ---
[INFO] Installing /home/nekop/tmp/foo/target/foo.war to /home/nekop/.m2/repository/foo/foo/1.0.0-SNAPSHOT/foo-1.0.0-SNAPSHOT.war
[INFO] Installing /home/nekop/tmp/foo/pom.xml to /home/nekop/.m2/repository/foo/foo/1.0.0-SNAPSHOT/foo-1.0.0-SNAPSHOT.pom
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.112s
[INFO] Finished at: Tue Dec 20 11:36:58 JST 2011
[INFO] Final Memory: 10M/499M
[INFO] ------------------------------------------------------------------------
***SUCCESS*** Build successful.

デプロイしてみます。

[foo] foo $ as7 deploy
Wrote /home/nekop/jboss710b1b/standalone/deployments/foo.war
***SUCCESS*** Deployed [foo.war] to [/home/nekop/jboss710b1b/standalone/deployments]

アクセスするとこんな感じのテンプレート画面が表示されますが、左下にエンティティの一覧があって、クリックするとそれぞれのデータの操作画面になります。

Addressをクリックするとこんな感じ。データが一覧表示され、検索とデータの操作ができるようになっています。

ショーケースの例もそうですが、Forgeを利用する一連の手順をスクリプト化してどこでも再現できる、という面白い機能があります。デモを行うときに便利ですし、スクリプトを流すだけなのでハンズオンも簡単、さらにスクリプトファイルをちょこちょこ変えるだけで似たようなプロジェクトが作れます。僕はJPAのテストをしたりだとか、ちょこっと機能を試すだけのプロジェクトを生成したりするのに使っています。

https://raw.github.com/forge/core/master/showcase/posale.fsh

また、Forgeのシェル環境ではGitが普通に使えるので、何かを試してイマイチだったら捨てる、というのが高速に行えるようになっています。

Forge(というかこの手の開発支援ツール全てに当てはまると思いますが)は慣れるまで多少時間がかかりますが、慣れてしまえば超速Java EEアプリケーション開発の恩恵を受けることができて便利ですね。