2015-05-15 9 views
12

Próbuję napisać kontroler REST Grails, który powinien zawsze odpowiadać JSON. Sterownik znajduje się poniżej:Kontroler REST Grailsa odpowiada nieprawidłowym typem zawartości

class TimelineController { 

    static allowedMethods = [index: "GET"] 
    static responseFormats = ['json'] 

    TimelineService timelineService 

    def index(TimeLineCommand command) { 
     List<TimelineItem> timeline = timelineService.currentUserTimeline(command) 
     respond timeline 
    } 
} 

Używam metody respond który jest częścią wsparcia REST Grails', negocjacje więc treść jest używany, aby dowiedzieć się, jaki rodzaj odpowiedzi do renderowania. W tym konkretnym przypadku spodziewałbym JSON zostać wybrany, ponieważ kontroler określa

static responseFormats = ['json'] 

Ponadto pisałem (i zarejestrowane wiosną) Poniższy renderujący, aby dostosować format JSON, który jest zwracany do List<TimelineItem>

class TimelineRenderer implements ContainerRenderer<List, TimelineItem> { 

    @Override 
    Class<List> getTargetType() { 
     List 
    } 

    @Override 
    Class<TimelineItem> getComponentType() { 
     TimelineItem 
    } 

    @Override 
    void render(List timeline, RenderContext context) { 

     context.contentType = MimeType.JSON.name 
     def builder = new JsonBuilder() 

     builder.call(
      [items: timeline.collect { TimelineItem timelineItem -> 

       def domainInstance = timelineItem.item 

       return [ 
         date: timelineItem.date, 
         type: domainInstance.class.simpleName, 
         item: [ 
           id : domainInstance.id, 
           value: domainInstance.toString() 
         ] 
       ] 
      }] 
     ) 

     builder.writeTo(context.writer) 
    } 

    @Override 
    MimeType[] getMimeTypes() { 
     [MimeType.JSON] as MimeType[] 
    } 
} 

pisałem kilka testów funkcjonalnych i widać, że chociaż moja renderujący jest wywoływana, rozdzielonych typu treści text/html, więc kontroler zwraca 404, ponieważ nie może znaleźć GSP z oczekiwanym nazwy.

Podejrzewam, że problem jest związany z korzystaniem z niestandardowego renderera, ponieważ mam inny prawie identyczny kontroler, który nie używa niestandardowego renderera i poprawnie rozpoznaje typ zawartości.

+1

Czy nagłówek 'Accept' jest ustawiony na' application/json'? – dmahapatro

+0

@dmahapatro Nie chcę używać nagłówka 'Accept' dla rozdzielczości treści, ** zawsze ** chcę zwrócić JSON. Pomyślałem, że dodanie 'static responseFormats = ['json']' do kontrolera powinno zapewnić to –

+0

Czy mógłbyś trochę wyjaśnić, dlaczego właściwie chcesz w ogóle używać 'odpowiedzi'? Kiedy nie używasz różnych typów MIME, możesz w ogóle pozbyć się metody 'reply' i zamiast niej użyć' render myList jako JSON'? –

Odpowiedz

0
  1. W Config.groovy, należy podać grails.mime.types. Szczegóły można znaleźć tutaj: Grails 2.3.11 Content Negotiation. Przynajmniej trzeba mieć następujące w Config.groovy:

    grails.mime.types = [ 
        json: ['application/json', 'text/json'] 
    ] 
    
  2. Jeśli chcesz odpowiedzieć dostosowanych JSON, render someMap as JSON jest zalecane.

  3. O problemie z numerem 404 należy wykonać operację response.setContentType('application/json'). Domyślny format odpowiedzi Grails to html, dzięki czemu wyszuka plik gsp, aby wyrenderować, jeśli typ contentType nie jest określony.

+0

1. Mam już to 'Config.groovy' –

+0

2. Jeśli używam' render someMap jako JSON', wówczas będzie używane domyślne renderowanie JSON, tzn. 'TimelineRenderer' nie będzie wywoływane –

+0

3. Nie powinienem ustawiać nagłówka typu zawartości, rozdzielczość treści Grails powinna wybrać JSON na podstawie' static responseFormats = [' json '] ' –

6

Wygląda na to trzeba utworzyć pusty (co najmniej) index.gsp pod

grails-app/views/timeline/ 

aby uczynić pracę renderujący. Pomyślnie wracam do typu zawartości jako application/json

To zachowanie bardzo mnie niepokoi i wciąż się nad tym zastanawiam. To jest warte problemu z JIRA. Jeśli potrzebujesz, mogę przesłać moją sztuczną aplikację do github.

UPDATE:
Problem utworzony w github (linki próbki APP).
https://github.com/grails/grails-core/issues/716

+0

Tak, jeśli możesz wypchnąć swoją sztuczną aplikację do GitHub i/lub podnieść JIRA, która byłaby bardzo pomocna. Po przeprowadzeniu pewnych badań, zaczynam podejrzewać, że nie jest możliwe wykonanie renderera kontenera dla danego typu, chyba że masz także osobny renderer dla tego typu. Jednak, doktorzy nie wspominają o tym, i nie widzę żadnego logicznego powodu, dlaczego tak powinno być, więc zgadzam się, że to jest warte JIRA. –

+0

Aplikacja jest podobna do tego, co jest przedstawiane w pytaniu. Oto problem w github. https://github.com/grails/grails-core/issues/716 – dmahapatro

+1

dobra robota w wydaniu JIRA i aplikacji demo, dodałem komentarz do problemu –

Powiązane problemy