Spring Roo を使い始めたので、メモを残しておきます。
Roo は SpringSource のプロダクトで、コマンドラインからソースを自動生成するツールです。
バージョン1.0.0がリリースされたのが 2009年12月31日 というまだ新しいプロジェクトです。
その中でも今回使用した DBからのリバースエンジニアリングの機能については今年10月にリリースされた Roo1.1 で追加されたばかりの機能です。
今回の目的としては、新しく開発中のWebアプリケーションがあり、DBのスキーマやユーザにサービスを提供する側の画面は一通りできているのですが、管理者用の画面がまだなく、できるだけ作業コストをかけずに管理画面を実装したいということで、Roo のリバースエンジニアリングを使ってみることにしました。
Roo のインストールは簡単で、ダウンロードページからzipファイルをダウンロードして解凍し、$ROO_HOME/bin をPATHに通せばOKです。
作成するアプリケーション用のディレクトリを作成し、コマンドラインでそのディレクトリに移動して roo とコマンドを実行すると rooシェルというものが起動します。
C:\app\admin>roo
____ ____ ____
/ __ \/ __ \/ __ \
/ /_/ / / / / / / /
/ _, _/ /_/ / /_/ /
/_/ |_|\____/\____/ 1.1.0.RELEASE [rev 793f2b0]
Welcome to Spring Roo. For assistance press TAB or type "hint" then hit ENTER.
roo>
まずProjectを作成します。
roo> project --topLevelPackage com.admin Created C:\app\admin\pom.xml Created SRC_MAIN_JAVA Created SRC_MAIN_RESOURCES Created SRC_TEST_JAVA Created SRC_TEST_RESOURCES Created SRC_MAIN_WEBAPP Created SRC_MAIN_RESOURCES\META-INF\spring Created SRC_MAIN_RESOURCES\META-INF\spring\applicationContext.xml Created SRC_MAIN_RESOURCES\log4j.properties com.admin roo>
続けてDBの種別を設定します。PostgreSQL で Hibernate を使用しているので、下記のコマンドを実行します。
com.admin roo> persistence setup --provider HIBERNATE --database POSTGRES --userName user
Managed SRC_MAIN_RESOURCES\META-INF\spring\applicationContext.xml
Created SRC_MAIN_RESOURCES\META-INF\persistence.xml
Please enter your database details in src/main/resources/META-INF/spring/database.properties.
Created SRC_MAIN_RESOURCES\META-INF\spring\database.properties
Managed ROOT\pom.xml [Added dependency postgresql:postgresql:8.4-701.jdbc3]
Managed ROOT\pom.xml [Added dependency org.hibernate:hibernate-core:3.5.5-Final]
Managed ROOT\pom.xml [Added dependency org.hibernate:hibernate-entitymanager:3.5.5-Final]
Managed ROOT\pom.xml [Added dependency org.hibernate.javax.persistence:hibernate-jpa-2.0-api:1.0.0.Final]
Managed ROOT\pom.xml [Added dependency org.hibernate:hibernate-validator:4.1.0.Final]
Managed ROOT\pom.xml [Added dependency javax.validation:validation-api:1.0.0.GA]
Managed ROOT\pom.xml [Added dependency cglib:cglib-nodep:2.2]
Managed ROOT\pom.xml [Added dependency javax.transaction:jta:1.1]
Managed ROOT\pom.xml [Added dependency org.springframework:spring-jdbc:${spring.version}]
Managed ROOT\pom.xml [Added dependency org.springframework:spring-orm:${spring.version}]
Managed ROOT\pom.xml [Added dependency commons-pool:commons-pool:1.5.4]
Managed ROOT\pom.xml [Added dependency commons-dbcp:commons-dbcp:1.3]
Managed ROOT\pom.xml
com.admin roo>
次に今回のターゲットとなるDBを指定します。
com.admin roo> database properties set --key database.url --value jdbc:postgresql://appdb/appdb Managed SRC_MAIN_RESOURCES\META-INF\spring\database.properties com.admin roo>
そして下記コマンドを実行すると、DBからリバースエンジニアリングでJavaのEntityクラスが作成されます。
com.admin roo> database reverse engineer --package ~.domain --schema public
さらに下記コマンドで Controller や View などが作成されます。
com.admin roo> controller all --package ~.controller
作成されたProjectをEclipseで扱えるようにするには、下記コマンドを実行します。
com.admin roo> perform eclipse
作成されたProjectはMaven Projectなので、rooシェルを終了してから下記コマンドで Jetty を使ってアプリケーションを起動することができます。
C:\app\admin>mvn jetty:run
起動した際に下記の様なExceptionが発生することがあります。
2010-11-10 11:46:59.007:WARN::Failed startup of context JettyWebAppContext@12b2a85@12b2a85/admin,file:/C:/Documents%20an d%20Settings/h-akanuma/My%20Documents/workspace/admin/src/main/webapp/,file:/C:/Documents%20and%20Settings/h- akanuma/My%20Documents/workspace/admin/src/main/webapp/ java.net.URISyntaxException: Illegal character in path at index 18: file:/C:/Documents and Settings/h-akanuma/.m2/reposi tory/org/mortbay/jetty/jetty-maven-plugin/7.1.2.v20100523/jetty-maven-plugin-7.1.2.v20100523.jar
これはMavenのローカルリポジトリのパスにスペースが含まれているために発生するようで、ローカルリポジトリをスペースが含まれないパスに移動することで解消します。
また、さらに続行する中で下記のようなExceptionが発生したので、対処方法もあわせて書いておきます。
Caused by: org.hibernate.HibernateException: Wrong column type in public.sponsor_topic_access_count_history for column totaled_date. Found: date, expected: timestamp at org.hibernate.mapping.Table.validateColumns(Table.java:284) at org.hibernate.cfg.Configuration.validateSchema(Configuration.java:1174) at org.hibernate.tool.hbm2ddl.SchemaValidator.validate(SchemaValidator.java:139) at org.hibernate.impl.SessionFactoryImpl.(SessionFactoryImpl.java:389) at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1385) at org.hibernate.cfg.AnnotationConfiguration.buildSessionFactory(AnnotationConfiguration.java:954) at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:891) ... 51 more
これは Roo で作成されたEntityクラスとしては datetime型 を想定しているのにDBの型はdate型だったということのようで、「生成されたEntityの中の @Column で columnDefinition="DATE" を指定することで解消しました。」 ←この対応は間違いでした。Rooが生成するクラスは基本的に編集してはいけません。この場合は元のEntityにそのプロパティを定義して、自動生成されるクラスに含まれないようにする必要があります。
Caused by: org.hibernate.HibernateException: Missing sequence or table: hibernate_sequence
at org.hibernate.cfg.Configuration.validateSchema(Configuration.java:1185)
at org.hibernate.tool.hbm2ddl.SchemaValidator.validate(SchemaValidator.java:139)
at org.hibernate.impl.SessionFactoryImpl.(SessionFactoryImpl.java:389)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1385)
at org.hibernate.cfg.AnnotationConfiguration.buildSessionFactory(AnnotationConfiguration.java:954)
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:891)
... 65 more
これは Roo で作成されたEntityクラスの中で IDカラムのSequence の strategy が GenerationType.AUTO になっていたことによるもので、 「GenerationType.SEQUENCE に書き直すことで解消しました。」 ←こちらも上記同様生成されたクラスを編集せずに元のEntityの方にプロパティを定義する必要があります。
ひとまずここまででアプリケーションが起動するようになりました。
上記Exceptionを解消するまでに結構時間がかかってしまいましたが、これでCRUDの一通りの機能を持ったアプリができると考えると手軽ですね。
Roo の売りのひとつとして、一度作って終わりではなく、インクリメンタルにEntityとJavaのソースの内容を更新していけることだと思いますが、生成されたソースに手を加える必要があるとなると今後変更を加えていく場合にどのように対応できるかは要調査ですね。