2009/07/14

Grails AppEngine PluginでJPAを使用する(失敗)

Grails AppEngine pluginでJPAを使用するには

前日、以下のページにてjpaを使用する場合には追加でプラグイン入れないといけないという記述を見つけたので、再度google app engine開発の手順を整理してみる。 Grails - Plugin: Grails AppEngine plugin

開発環境構築から、Grails App Engine Pluginインストールまでの流れ

以前投稿したとおり。

ゲンゾウ用ポストイット: 勉強会に向けてGrails AppEngine Pluginについて調査

grails install-plugin app-engine

コマンドを実行した後は、

grails install-plugin gorm-jpa

コマンドを実行。

grails create-domain-class com.Book

で適当なドメインクラス作成後、

grails generate-all com.Book

でview、controller作成。

 

grails app-engine run

コマンドで動作確認。

book/list にアクセス

http://localhost:8080/にアクセス。ちゃんと動作するようになった。

http://localhost:8080/book/listにアクセスすれば、ちゃんと本の一覧画面が表示される。

http://localhost:8080/book/createで新規登録画面へ。ただここで登録しようとするとエラーとなってしまう。

org.codehaus.groovy.runtime.InvokerInvocationException: java.lang.NullPointerException
 at com.google.apphosting.utils.jetty.DevAppEngineWebAppContext.handle(DevAppEngineWebAppContext.java:54)
 at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:43)
 at com.google.apphosting.utils.jetty.DevAppEngineWebAppContext.handle(DevAppEngineWebAppContext.java:54)
 at com.google.appengine.tools.development.JettyContainerService$ApiProxyHandler.handle(JettyContainerService.java:306)
Caused by: java.lang.NullPointerException
 at org.datanucleus.jpa.EntityManagerImpl.find(EntityManagerImpl.java:204)
 at org.datanucleus.store.appengine.jpa.DatastoreEntityManager.find(DatastoreEntityManager.java:48)
 at org.grails.jpa.JpaPluginSupport$__clinit__closure3_closure6_closure11_closure19.doCall(JpaPluginSupport.groovy:253)
 at com.BookController$_closure3.doCall(BookController.groovy:18)
 at com.BookController$_closure3.doCall(BookController.groovy)
 ... 4 more


プラグインの説明サイトを見ていると grails generate-all com.Book
にて作成したcontrollerでは正常に動作せず、手を加える必要があるようだ。

For example:

def jpaTemplate
def transactionTemplate
def save = {
   transactionTemplate.execute( { status -> 
        def album = new Album(params)
 if(!album.hasErrors() && album.validate() ) {
  jpaTemplate.persist(album)
  jpaTemplate.flush()
  flash.message = "Album ${albumInstance.id} created"
  redirect(action:show,id:album.id) 
 }
 else {
  status.setRollbackOnly()    
  render(view:'create',model:[album:album])    
 }

} as TransactionCallback )
}

面倒くさい

ということで、夜にでもjdoで試してみたい。

jdoだとGORMは使えないんだよね。でもgenerate-allコマンドでviewcontrollerを自動生成してくれるから一長一短か。

 

2 件のコメント:

  1. ゲンゾウさんこんにちは。
    どんなドメインクラスを作りましたか?

    https://svn.codehaus.org/grails-plugins/grails-gorm-jpa/trunk/grails-app/domain/org/acme/Person.groovy

    をみると、JPAのアノテーションが必要みたいです。ただ、これをやってさらに
    ●nativeジェネレータの問題に関する例外が発生するのでidを以下のように定義する。

    @Id
    // @GeneratedValue (strategy = GenerationType.AUTO)
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    Long id

    とすることで、私はローカル開発サーバ
    では動かせました。ただ、以下の問題がクリアできず
    本番サーバでは動作させるまでには行きませんでした。

    http://artofsystems.blogspot.com/2009/07/popstat-on-google-app-engine.html
    http://code.google.com/p/googleappengine/issues/detail?id=1240#c5

    返信削除
  2. >uehajさん
    情報ありがとうございます。
    どうやら以下のサイトからサンプルをコピーしたのですが、それに誤りがあったためのようです。
    (ちゃんと確認していれば…)

    Grails - Plugin: Grails AppEngine plugin [http://www.grails.org/plugin/app-engine]

    def jpaTemplate
    def transactionTemplate
    def save = {
    transactionTemplate.execute( { status ->
    def album = new Album(params)
    if(!album.hasErrors() && album.validate() ) {
    jpaTemplate.persist(album)
    jpaTemplate.flush()
    flash.message = "Album ${albumInstance.id} created" // <<=ここがおかしい
    redirect(action:show,id:album.id)
    }
    else {
    status.setRollbackOnly()
    render(view:'create',model:[album:album])
    }

    } as TransactionCallback ) }


    ただし、新たな問題と奮闘中ですw

    返信削除