ForgeはJava EE6を利用したWebアプリケーション(のひな形)の作成 〜 アプリケーションサーバへのディプロイまで可能なコマンドラインツールです。作成されるアプリケーションはMavenプロジェクトのため、そのままIDE等で開くことができます。
また、プラグインによりサポートするフレームワークやAPサーバが追加できします。自分でプラグインを作成することもできます。
今回はForgeでJPAとJSFを使ったサンプルアプリケーションを作ってみます。
まず、Forgeをダウンロードして展開します。
$ https://repository.jboss.org/nexus/service/local/artifact/maven/redirect?r=releases&g=org.jboss.forge&a=forge-distribution&v=1.0.5.Final&e=zip
$ unzip Downloads/forge-distribution-1.0.5.Final.zip
環境変数を設定します。
export FORGE_HOME=~/forge-distribution-1.0.5.Final/
export PATH=$PATH:$FORGE_HOME/bin
forgeコマンドでforgeのシェルを起動します。
list-commandで利用可能なコマンドを確認できます。–allを付けないと現在のコンテキストで利用可能なコマンドのみ表示されます。OSのコマンドやgit、mavenもforgeから呼び出すことができます。
$ forge
_____
| ___|__ _ __ __ _ ___
| |_ / _ \| `__/ _` |/ _ \ \\
| _| (_) | | | (_| | __/ //
|_| \___/|_| \__, |\___|
|___/
[no project] kenichiro22 $ list-commands --all
[FILE & RESOURCES]
cat* cd*
edit* find*
fingerprint* grep*
list-web-resources* ls
ls* mkdir*
mv* open*
pick-up* pwd*
pwr* rm*
wc*
[OTHER]
alias* beans list-alternatives*
beans list-decorators* beans list-interceptors*
beans new-bean* beans new-conversation
beans setup* constraint AssertFalse
constraint AssertTrue constraint DecimalMax
constraint DecimalMin constraint Digits
constraint Future constraint Max
constraint Min constraint NotNull
constraint Null constraint Past
constraint Pattern constraint Size
constraint Valid ejb setup*
entity* faces new-view*
faces project-stage* faces setup*
faces* field
field boolean field custom
field int field long
field manyToMany field manyToOne
field number field oneToMany
field oneToOne field string
field temporal git clone*
git git-checkout* git setup*
i18n add-locale* i18n faces-setup*
i18n get* i18n put*
i18n remove* i18n setup*
java list-imports java new-class*
java new-enum-const java new-enum-type*
java new-field java new-method
java* jms setup*
jstl setup* jta setup*
persistence setup* persistence*
plugins new-plugin* plugins setup*
remove-constraint rest endpoint-from-entity*
rest setup* servlet setup*
servlet* soap setup*
unalias* validation setup*
[PROJECT]
build* execute-java*
maven remove-parent* maven set-artifactid*
maven set-groupid* maven set-parent*
maven set-version* mvn*
new-project* project add-dependency*
project add-known-plugin-repository* project add-known-repository*
project add-managed-dependency* project add-plugin-repository*
project add-repository* project find-dependency*
project find-managed-dependency* project install-facet*
project list-dependencies* project list-facets*
project list-managed-dependencies* project list-plugin-repositories*
project list-properties* project list-repositories*
project remove-dependency* project remove-facet*
project remove-managed-dependency* project remove-plugin-repository*
project remove-property* project remove-repository*
project set-property* project*
setup* shade exclude*
shade include* shade make-executable*
shade relocate* shade remove*
shade reset* shade setup*
test*
[SHELL ENVIRONMENT]
about* clear*
echo* exec*
exit* forge find-plugin*
forge git-plugin* forge install-plugin*
forge list-plugins* forge remove-plugin*
forge restart* forge source-plugin*
forge* help*
less* list-commands*
list-config* list-properties*
more* reset*
run* run-url*
set* version*
wait*
[UI GENERATION & SCAFFOLDING]
list-scaffold-providers* scaffold from-entity*
scaffold indexes* scaffold setup*
scaffold templates*
[VERSION CONTROL]
git*
(* = command accessible from current context)
プロジェクトを作成します。
[no project] kenichiro22 $ new-project --named try-forge --topLevelPackage com.azuki3.forge --projectFolder workspace/try-forge
***SUCCESS*** Created project [try-forge] in new working directory [/Users/kenichiro22/workspace/try-forge]
scaffoldの設定を行います。JSFを使います。
[try-forge] try-forge $ scaffold setup --scaffoldType faces
? Scaffold provider [faces] is not installed. Install it? [Y/n] Y
? 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] Y
***SUCCESS*** Installed [forge.maven.WebResourceFacet] successfully.
JPAの設定を行います。 JPAプロバイダーとコンテナを指定します。JPAプロバイダーはHibernateをコンテナはJBoss AS7を指定してみます。
[try-forge] try-forge $ persistence setup --provider HIBERNATE --container JBOSS_AS7
***INFO*** Setting transaction-type="JTA"
***INFO*** Using example data source [java:jboss/datasources/ExampleDS]
? The JPA provider [HIBERNATE], also supplies extended APIs. Install these as well? [y/N]
***SUCCESS*** Persistence (JPA) is installed.
ここから実際のアプリケーションを作成します。
まず、Entityを作成します。今回はリレーションを試してみたいので、User - Blog - Tagという3つのEntityを作成します。BlogとUserがManyToOneでBlogとTagがManyToManyです。
[try-forge] try-forge $ entity --named User
? In which package you'd like to create this @Entity, or enter for default [com.azuki3.forge.model]
Created @Entity [com.azuki3.forge.model.User]
Picked up type : com.azuki3.forge.model.User
[try-forge] User.java $ field string --named name
Added field to com.azuki3.forge.model.User: @Column private String name;
[try-forge] User.java $ field string --named email
Added field to com.azuki3.forge.model.User: @Column private String email;
[try-forge] User.java $ entity --named Blog
Created @Entity [com.azuki3.forge.model.Blog]
Picked up type : com.azuki3.forge.model.Blog
[try-forge] Blog.java $ field string --named title
Added field to com.azuki3.forge.model.Blog: @Column private String title;
[try-forge] Blog.java $ field string --named content
Added field to com.azuki3.forge.model.Blog: @Column private String content;
[try-forge] Blog.java $ field temporal --named createdAt --type TIMESTAMP
Added field to com.azuki3.forge.model.Blog: private @Temporal(TemporalType.TIMESTAMP) Date createdAt;
[try-forge] Blog.java $ field manyToOne --named user --fieldType com.azuki3.forge.model.User
[try-forge] Blog.java $ entity --named Tag
Created @Entity [com.azuki3.forge.model.Tag]
Picked up type : com.azuki3.forge.model.Tag
[try-forge] Tag.java $ field string --named name
Added field to com.azuki3.forge.model.Tag: @Column private String name;
[try-forge] User.java $ field manyToMany --named tag --fieldType com.azuki3.forge.model.Tag.java
Blogにバリデーションを追加します。
[try-forge] Blog.java $ validation setup --provider JAVA_EE
***SUCCESS*** Installed [forge.spec.validation] successfully.
[try-forge] Blog.java $ constraint NotNull --onProperty title
Constraint NotNull has been successfully added on property named 'title'
[try-forge] Blog.java $ constraint NotNull --onProperty content
Constraint NotNull has been successfully added on property named 'content'
[try-forge] Blog.java $ constraint Size --onProperty title --min 1 --max 256
Constraint Size has been successfully added on property named 'title'
[try-forge] Blog.java $ constraint Size --onProperty content --min 1 --max 256
Constraint Size has been successfully added on property named 'content'
[try-forge] Blog.java $ constraint NotNull --onProperty user
Constraint NotNull has been successfully added on property named 'user'
EntityからJSFのscaffoldを作成します。
[try-forge] try-forge $ scaffold from-entity com.azuki3.forge.model.Blog.java ***INFO*** Using currently installed scaffold [faces]
? [/Users/kenichiro22/workspace/try-forge/src/main/webapp/resources/scaffold/pageTemplate.xhtml] File exists, overwrite? [Y/n]
***SUCCESS*** Generated UI for [com.azuki3.forge.model.Blog]
ビルドしてJBoss AS7にディプロイします。JBoss AS7は別途起動しておきます。
[try-forge] try-forge $ build
[try-forge] try-forge $ as7 deploy
こんな感じの画面ができます。ManyToOne, ManyToManyの関連も自動作成されます。ただ、バリデーションは動作しませんでした。もともとサポートされていないのか、私の使い方が悪いのかはわかりません。。
これくらいできれば、PlayやGrailsのscaffoldと同じくらいのことはできるでしょうか。
ついでにREST APIも作成します。
[try-forge] try-forge $ rest setup --activatorType APP_CLASS
? What root path do you want to use for your resources? [/rest]
? In what package do you want to store the Application class? com.azuki3.forge.
rest
? How do you want to name the Application class? [RestApplication]
***SUCCESS*** Installed [forge.spec.jaxrs.applicationclass] successfully.
***SUCCESS*** Rest Web Services (JAX-RS) is installed.
[try-forge] try-forge $ rest endpoint-from-entity com.azuki3.forge.model.Blog.java
***SUCCESS*** Generated REST endpoint for [com.azuki3.forge.model.Blog]
他にもi18n用のファイルの作成や、JAX-RSからEJBまでなどひと通りのJavaEE用のコマンドがあるようです。
今回使ってみた感想ですが、、コマンドの補完機能を備えているので非常に使いやすいです。Scaffoldまで使わなくても、Java EE6をサポートしたコンテナを使い場合でもpom.xmlに各APIのライブラリを追加するのは結構面倒なので、それだけでも助かります。プラグインがどんどん増えてJava EE6以外のライブラリも簡単に使えるようになるといいですね。プラグインは、"find-plugin"コマンドで検索できるようなのですが、どこかで一覧でも見られるページはないのでしょうか。
あとscaffoldのテンプレートにTwitter bootstrapが使えたらいいですね。さらに、JSFの他にGWTでCRUDが作れたりすると助かるのですが。GWT用プラグインもあるので、どんなものかはそのうち試してみたいと思います。
今回のサンプルアプリケーションのコードは以下にあります。
https://github.com/kenichiro22/try-forge-scaffold