2015-02-10 15 views
0

我在Grails 2.4.4中構建了一個REST API,並依靠RestfulController來處理基本的CRUD類型功能。前端是在AngularJS 1.3中構建的,大部分Angular的$ resource和Grails RestfulController都可以完美工作,並且不需要我編寫大量的樣板代碼。我有一個主要問題,但是當我將JSON從Angular發佈到Grails時,具有hasMany關係的域對象不會如預期那樣綁定。RestfulController在POST中不綁定嵌套的JSON

例如採取以下域對象:

class Task { 

    String name 
    //auto timestamps 
    Date dateCreated 
    Date lastUpdated 

    static hasMany = [filters:TaskFilter] 

    static constraints = { 
    } 

} 

class TaskFilter { 

    String filterMetaData 

    static belongsTo = [task:Task] 

    static constraints = { 
    task column: 'task_id' 
    } 
} 

當我發佈一個對象像這樣的例子:

{name: "Task 1", filters: [{filterMetaData:'some-meta-data'}]} 

我得到的Grails以下錯誤:

| Error 2015-02-10 17:41:34,619 [http-bio-8080-exec-5] ERROR errors.GrailsExceptionResolver - NullPointerException occurred when processing request: [POST] /api/studies/1/tasks 
Stacktrace follows: 
Message: null 
    Line | Method 
->> 99 | $tt__save   in grails.rest.RestfulController 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
| 198 | doFilter   in grails.plugin.cache.web.filter.PageFragmentCachingFilter 
|  63 | doFilter . . . . . in grails.plugin.cache.web.filter.AbstractFilter 
| 104 | processFilterChain in com.odobo.grails.plugin.springsecurity.rest.RestTokenValidationFilter 
|  71 | doFilter . . . . . in  '' 
|  53 | doFilter   in grails.plugin.springsecurity.web.filter.GrailsAnonymousAuthenticationFilter 
| 122 | doFilter . . . . . in com.odobo.grails.plugin.springsecurity.rest.RestAuthenticationFilter 
|  82 | doFilter   in grails.plugin.springsecurity.web.authentication.logout.MutableLogoutFilter 
|  63 | doFilter . . . . . in com.odobo.grails.plugin.springsecurity.rest.RestLogoutFilter 
|  82 | doFilter   in com.brandseye.cors.CorsFilter 
| 1145 | runWorker . . . . in java.util.concurrent.ThreadPoolExecutor 
| 615 | run    in java.util.concurrent.ThreadPoolExecutor$Worker 
^ 745 | run . . . . . . . in java.lang.Thread 

我不太確定這個錯誤是怎麼回事,因爲它很模糊,但是Task和TaskFilt呃回滾,沒有任何東西被保存。

奇怪的是,如果我從TaskFilter去掉這行代碼:

static belongsTo = [task:Task] 

一切正常,只不過這則迫使我有一個task_task_filter連接表,而不是更容易神交task_filter表中的task_id列。

我一直在這裏和各種論壇,博客和郵件列表上閱讀過去幾天的帖子,還沒有找到解決方案。大多數帖子都比較老,所以我不知道它們是否適用,但有幾個簡單地說「你不能使用Grails綁定JSONArray」,這看起來很奇怪,因爲對於任何中等複雜的數據模型來說,這是一個常見的要求。

無論如何 - 如果任何人都可以指出我具體和當前的事情,要麼說「你不能這樣做」,要麼如何真正處理這種情況,我將不勝感激。如果可能的話,我寧願避免編寫自定義分析代碼來管理這個,因爲RestfulController的其餘部分像魅力一樣工作。此外,如果有任何解釋爲什麼這個作品,當我刪除了關係的belongsTo方,也許這將幫助我瞭解這裏發生了什麼。

以防萬一你想知道我的RestfulController子類看起來是這樣的:

class TaskController extends RestfulController<Task> { 

    static responseFormats = ['json', 'xml'] 

    TaskController() { 
    super(Task) 
    } 
} 
+0

深入挖掘日誌之後,我意識到問題在於Task(任務資源)上調用save()時TaskFidter未設置task_id,導致Task上出現Null驗證錯誤(錯誤消息從不起泡,我可以看到,所以很難說出將事情輸出到控制檯上會發生什麼)。有一個JIRA公開適用,所以希望有一個解決方案即將出臺。 https://jira.grails.org/browse/GRAILS-11987 – earthtrip 2015-02-18 19:59:45

回答

0

後與Grails的開發團隊多次討論,我被告知,我的這個應該怎麼理解的工作不是Grails的方式作品。我認爲(不正確)是因爲數據綁定將TaskFilter添加到Task中,它將像在Task上調用addToFilters()一樣行爲,但不管創建集合的方式如何。我不知道集合究竟是什麼,但它絕對是不是保存它們。

JIRA已關閉爲「行爲如預期」。

我在此之後的解決方法是在我TaskController以下

@Override 
protected Task createResource() { 
    Task task = super.createResource() 
    if (task.filters) { 
    task.filters.each {filter -> 
     task.addToFilters(filter) 
    } 
    } 
    task 
} 

不幸的是在基於RestfulController應用程序將需要此相同類型的代碼來處理嵌套資源的任何關聯。我仍然認爲Grails應該在框架中處理這個問題,如果我能找到時間去處理它,我可以嘗試將代碼添加到代碼中。