Grails

Grails （グレイルズ）は、プログラミング言語 Groovy を使用するオープンソースのWebアプリケーションフレームワーク。Grails や Groovy はJavaプラットフォーム上で動作する。「設定より規約 (convention over configuration)」というパラダイムにより高い生産性を実現し、スタンドアロンの開発環境を提供しつつ、開発者からはその設定の詳細を隠蔽している。 かつては "Groovy on Rails" と名乗っていたが、Ruby on Rails の David Heinemeier Hansson の要求で現在の名称になった。開発は2005年7月に開始され、2006年3月29日に 0.1 をリリース、2008年2月18日に 1.0 をリリース、2011年12月15日に 2.0、2015年3月31日に 3.0 をリリースした。 Grails は以下のような目標を掲げて開発されてきた。 Javaプラットフォームの高生産性のWebフレームワークとする。 Hibernate や Spring Framework といった既に広く使われているJavaテクノロジーを単純で一貫したインタフェースで再利用する。 一貫性があり習得が容易なフレームワークとする。 フレームワークを構成する各部分についてユーザーに分かりやすい文書を提供する。 複雑で一貫性のない分野でユーザーが期待するものを提供する。 強力で一貫した永続性フレームワーク GSP (Groovy Server Pages) を使った強力で使いやすいビューテンプレート Webページコンポーネントを簡単に作成できるダイナミックタグライブラリ 容易に拡張/カスタマイズ可能なAjaxサポート フレームワークの威力を示すためのサンプルアプリケーションを提供する。 Webサーバや自動リソース再ロード機能など、完全な開発環境を提供する。 Grails は習得しやすく、アプリケーション開発と拡張が容易となるよう設計された。一貫性と強力な機能との正しいバランスを保つことを心がけている。 Grails は従来のJavaによるWeb開発フレームワークに比べて生産性を高めるため、以下の3つの特徴を備えている。 XMLコンフィギュレーション不要 即座に使える開発環境 Mixin経由の機能 JavaによるWebアプリケーション作成では、開発開始時点や途中で環境やフレームワークの構成設定が必要である。そのコンフィギュレーションは XML ファイルとして切り出して設定しやすくし、構成設定をアプリケーションのコードに埋め込まないようにすることが多い。 XML によるコンフィギュレーションはアプリケーション間の一貫性を高めるということで当初は歓迎された。しかし最近では、有効性は認めるものの、実際にXMLファイルの設定を修正するのは面倒だという人が多くなっている。アプリケーションが成長するにつれて、開発者はフレームワークのコンフィギュレーションを理解し、維持することに時間を費やすことになり、生産性を低下させる要因になっている。アプリケーションに機能を追加したり修正したりする度にXMLコンフィギュレーションも修正していると、アプリケーションの改良が遅くなり、生産性が低下する。 Grails では、XMLコンフィギュレーションファイルの修正を不要にした。その代わり、フレームワークが規約を使ってアプリケーションのコードを調べる。例えば、grails-app/controllers フォルダ内の名前の最後が Controller となっているクラス（例えば BookController）は、MVCのコントローラと見なされる。対応するビューも無指定の場合は grails-app/views/コントローラ名/アクション名.gsp となる。 ただし、設定が全くないわけではなく、データベースやログの設定などは ConfigSlurper の形式で grails-app/conf フォルダ内に配置する。ここの設定は GrailsApplication.config から読み込める。 従来のJavaによるWebツールキットでは、開発環境の整備は開発者が行わなければいけなかった。Grails は完全な開発環境を備えており、Webサーバ（Apache Tomcat）やデータベース（H2 Database）なども含んでいて、即座に使用することができる。全ての必要なライブラリはディストリビューションに含まれており、JavaのWeb環境も自動的に用意する。 grails run-app で内蔵サーバーを起動できるが、この場合は、開発モードになり、ソースコードの変更は自動的にリロードされ、適用される。開発モードの場合、初期設定は、H2 Database のオンメモリデータベースとなっている。本番環境向けは、grails war で war ファイルにまとめ、Apache Tomcat などに配備することができる。 Grails はいくつかのクラス上で Mixin 経由の動的メソッドを用意している。Grails では Mixin はメソッドである。Mixin はクラスに動的に追加される機能であり、あたかもその機能がプログラム上でコンパイルされたかのように利用できる。 この動的メソッドは、クラスを拡張したりインタフェースを実装したりすることなく、操作を実行できるようにする。Grails では、クラスの種類に基づいて動的メソッドを提供する。例えば、ドメインクラスはセーブ/削除/検索などの永続性操作を自動化するメソッドを持っている。 Grails は、MVCパラダイムにしたがって設計されている。ここでは、コントローラとビューについて解説する。モデル(ドメインクラス)については後述する。 Grails のアプリケーションは、以下のような grails コマンドによって作成される。 grails create-app myapp このコマンドによって、myapp ディレクトリ配下にGrailsアプリケーションに必要なディレクトリ構造やライブラリ等の雛形が生成される。 Grails はWebページの振る舞いを実装するのにコントローラを使う。以下のコードはコントローラの例である。 class BookController { def list() { [ books: Book.findAll() ] } } 1つのコントローラは複数のアクションを持ち、上のコントローラには list アクションがあり、データベース内の全ての本を含むモデルを返す。戻り値として 連想配列内で books を返しているが、これはビューから参照できる。上記例はビューのファイル名が無指定なので、grails-app/views/book/list.gsp になる。 このコントローラを生成するには、grails create-controller book コマンドを使う。grails-app/controllers ディレクトリにクラスが作成される。コントローラクラスは作成するだけで Grails に認識される。list アクションは http://ドメイン名/myapp/book/list にマッピングされる。 コントローラで XML や JSON などを返したいときは以下のように行える。 import grails.converters.* class BookController { def json() { render Book.list() as JSON } } Grails は GSP (Groovy Server Pages) と JSP をサポートしている。基本的には GSP を使用する。以下のコード例は GSP で書かれたビューであり、上記のコントローラが用意したモデル内の本のリストを表示する。 <!doctype html> <html> <head> <title>Our books</title> </head> <body> <ul> <g:each in="${books}"> <li>${it.title} (${it.author.name})</li> </g:each> </ul> </body> </html> デフォルトのファイル名の命名規則は grails-app/views/コントローラ名/アクション名.gsp であり、このビューはGrailsプロジェクトの grails-app/views/book/list.gsp として保存する。この位置に保存することで BookController と list アクションにマッピングされる。また、この位置に置くだけで Grails がこれをビューとして認識する。 GSP では ${} の部分で変数やメソッドを利用できる。標準設定はエスケープされずにそのまま出力されるが、grails-app/conf/Config.groovy の grails.views.default.codec を html にすると、HTMLエスケープして出力される。 Grails は、バージョン 2.0 以降、標準で jQuery サポートを取り込んでいる。また、プラグイン等で OpenRico、Prototype、Yahoo! UI libraryといった Ajax ライブラリをサポートしている。AjaxコードとHTMLを生成する既存のタグライブラリを利用できる。また、自前のタグライブラリを生成するのも容易である。 Grails は各種タグライブラリを提供するが、同時に自前のタグライブラリ(タグリブ)を簡単に作成できる。 class ApplicationTagLib { def formatDate = { attrs, body -> out << new java.text.SimpleDateFormat(attrs.format).format(attrs.date) } } この formatDate タグライブラリは java.util.Date オブジェクトを String にフォーマットする。このタグライブラリは grails-app/taglib/ApplicationTagLib.groovy ファイルに追加するか、ファイル名の末尾を TagLib.groovy として grails-app/taglib ディレクトリに置く。 以下は、GSP で formatDate タグライブラリを使ったコード断片である。 <g:formatDate format="yyyyMMdd" date="${myDate}"/> ダイナミックタグライブラリを GSP で使う場合、インポートタグを使う必要がない。ダイナミックタグライブラリはJSPファイルでも使えるが、GSPよりも若干作業が多い。 Grailsで扱うデータ(モデル)は、GORM (Grails Object Relational Mapping) と呼ばれるORマッピング機構を使ってデータベースに格納される。ドメインクラスは、以下のような grails コマンドを使って作成し、grails-app/domain ディレクトリ配下に配置する。 grails create-domain-class myapp.Book すると、ドメインクラス名を聞かれるので入力すると、適当なファイルが作成される。以下に Book クラスのコードを示す。 class Book { String title Person author } 上のドメインクラスは、書籍名をString型の title、著者を Person型の author として持つデータモデルを定義している。 GORMの機能によって、Grailsアプリケーション実行時にこのドメインクラスに対応するテーブル book がDB上に作成され、このテーブルは数値型の id、数値型のversion、 文字列型の title、 personテーブルのidへの外部キーである author_id の4つのカラムを持つ。Grailsアプリケーション開発者は、SQLをほとんど意識せず、ドメインクラスのメソッドとしてこれらのデータへのアクセスを記述することができる(もちろん、必要に応じてGORMのバックエンドであるHibernateが処理可能なHQLの形式でクエリを発行することもできる)。 このように、ドメインクラスを作成するだけで、Grails によって永続化されたデータを管理できる。ドメインクラスに主キーのためのidとバージョン管理のためのversionが明示的に宣言されていない場合にもそれらを付加する機能は、Grails 0.3 以降の GORM で提供されている。 Grailsは、ドメインクラスからコントローラやビューを自動生成する機能も提供している。これはScaffoldと呼ばれる機能で、静的Scaffoldと動的Scaffoldの2種類のScaffoldが提供されている。 静的Scaffoldを行うには、ドメインクラス Book を作成した後に以下のようなコマンドを使う。 grails generate-all myapp.Book このコマンドによって、基本的な CRUD (Create, Read, Update, Delete) 操作をすべて行うことができる雛形が生成される。コントローラ BookController や、4つのビュー list.gsp、 create.gsp、 edit.gsp、 show.gsp などである。このScaffoldによって、Grailsアプリケーション開発者は、ドメインクラスを記述するだけで基本的なCRUD操作が可能なWebアプリケーションの雛形を得ることができる。 また、コントローラに以下のように記述することで、任意のドメインクラスを動的Scaffoldすることができる。 class BookController { static scaffold = true } 動的Scaffoldは、静的Scaffoldのようなファイル生成を行わず、CRUD 操作を http://localhost:8080/myapp/book/ 上で提供する。 GORMで管理されるドメインクラスには、クラスおよびオブジェクト上で永続性操作を行う動的メソッドと静的メソッドがある。 save() メソッドはオブジェクトをデータベースにセーブする。 def book = new Book(title:"The Da Vinci Code", author:Author.findByName("Dan Brown")) book.save() delete() メソッドはオブジェクトをデータベースから削除する。 def book = Book.findByTitle("The Da Vinci Code") book.delete() refresh() メソッドはオブジェクトの状態をデータベースに基づいて更新する。 def book = Book.findByTitle("The Da Vinci Code") book.refresh() ident() メソッドはデータベースからそのオブジェクトに割り当てられたIDを取り出す。 def book = Book.findByTitle("The Da Vinci Code") def id = book.ident() count() メソッドは、指定されたクラスについて、データベース上のレコード数を返す。 def bookCount = Book.count() exists() メソッドは、指定されたIDのオブジェクトがデータベース上に存在するかどうかをブーリアンで返す。 def bookExists = Book.exists(1) find() メソッドは、指定されたオブジェクトクエリ文でデータベースから見つかった最初のオブジェクトを返す。 def book = Book.find("from Book b where b.title = ?", [ 'The Da Vinci Code' ]) この場合のクエリ構文は Hibernate HQL である。 findAll() メソッドは、データベースに存在する全オブジェクトを返す。 def books = Book.findAll() findAll() メソッドは、クエリ文を指定し、それにマッチした全オブジェクトのリストを返す。 def books = Book.findAll("from Book") findBy*() メソッドは、指定したパターンにマッチした最初のオブジェクトを返す。 def book = Book.findByTitle("The Da Vinci Code") または: def book = Book.findByTitleLike("%Da Vinci%") findAllBy*() メソッドは、指定したパターンにマッチした全オブジェクトのリストを返す。 def books = Book.findAllByTitleLike("The%") findWhere*() メソッドは、一連のパラメータにマッチした最初のオブジェクトを返す。 def book = Book.findWhere(title:"The Da Vinci Code") GORMの永続性機構は Hibernate を使って実装されている。そのため、古いデータベースであっても標準の Hibernate mapping ファイルを使ってGORMクラスにマッピングできる。 Grails はJavaプラットフォーム上に構築されているため、Javaライブラリ、フレームワーク、既存コードベースとの連携が容易である。特に Hibernate ORMフレームワークとはクラスの透過的連携を実現している。したがって、Hibernate を使った既存アプリケーションを再コンパイルや再設定することなく、上述の動的永続性メソッドを使ってGrailsを使うことができる。 その結果、Hibernate にマッピングされたJavaクラスのために scaffolding を設定できる。また、Grails Webフレームワークの機能は全て、これらのクラスとそれを使うアプリケーションに使用可能である。