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

2019-02-21Grails,Groovy

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

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

開発環境構築から、Grails App Engine 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では正常に動作せず、手を加える必要があるようだ。

(例)

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 を自動生成してくれるから一長一短か。

2019-02-21Grails,Groovy