6

I'm using the support for REST introduced by Grails in 2.3. My app includes the following domain classes:

@Resource(formats=['json', 'xml'])
class Sensor {
    String name
    static hasMany = [metrics: Metric]
}

@Resource(formats=['json', 'xml'])
class Metric {

    String name
    String value

    static belongsTo = [sensor: Sensor]
}

And in UrlMappings.groovy I've defined the following nested RESTful URL mappings:

"/api/sensors"(resources: 'sensor') {
    "/metrics"(resources: "metric")
}

If I navigate to the URL /api/sensors/1/metrics I expect the response to show all Metric instances associated with the Sensor with ID 1, but in fact it returns all Metric instances (up to a limit of 10)

  • Is there a URL that will return only Metric instances associated with a particular Sensor instance (without implementing my own controller)?
  • Is there a way to override the default limit of 10 results (without adding a max parameter to the request)?
Dónal
  • 185,044
  • 174
  • 569
  • 824
  • In regards to changing the limit when using Resource, the answer is no. There was a previous discussion about this already on here. The reasoning behind this design choice was that Resource was designed to be quick and easy, with generating and modifying the controllers as the next level of customization. My previous answer to this has pointers to the Grails source to demonstrate that Resource doesn't allow this customization. – Joshua Moore Mar 26 '14 at 23:32
  • http://stackoverflow.com/questions/22336804/change-default-for-max-attribute-on-results-for-resource-on-domain-classes-for/22337550#22337550 – Joshua Moore Mar 26 '14 at 23:34
  • @JoshuaMoore thanks, do you know if it's possible to get the `Metric` instances for a single `Sensor` instance? – Dónal Mar 26 '14 at 23:39
  • Never used them but according to the docs: http://grails.org/doc/2.3.x/guide/single.html#restfulMappings which appears to be what you have. – Joshua Moore Mar 26 '14 at 23:45
  • Let know if there is a better way than the provided answer. :) – dmahapatro Mar 29 '14 at 23:54
  • @dmahapatro I think extending `RestufulController` and overriding `queryForResource` might be slightly better http://grails.org/doc/latest/guide/webServices.html#extendingRestfulController – Dónal Mar 31 '14 at 01:31

1 Answers1

6

Looks like it isn't that simple. :) We can get a vivid picture if this command is run:

grails url-mapping-report

to see

Controller: metric
 |   GET    | /api/sensors/${sensorId}/metrics           | Action: index  |
 |   GET    | /api/sensors/${sensorId}/metrics/create    | Action: create |
 |   POST   | /api/sensors/${sensorId}/metrics           | Action: save   |
 |   GET    | /api/sensors/${sensorId}/metrics/${id}     | Action: show   |
 |   GET    | /api/sensors/${sensorId}/metrics/${id}/edit| Action: edit   |
 |   PUT    | /api/sensors/${sensorId}/metrics/${id}     | Action: update |
 |  DELETE  | /api/sensors/${sensorId}/metrics/${id}     | Action: delete |

So, we would at least need a MetricController inheriting RestfulController and override index() to do an additional check for Metric and return list based on Sensor as shown below:

class MetricController extends RestfulController<Metric> {
    static responseFormats = ['json', 'xml']

    MetricController() {
        super(Metric)
    }

    @Override
    def index() {
        def sensorId = params.sensorId
        respond Metric.where {
            sensor.id == sensorId
        }.list()
    }
}

Above changed would provide the expected result (including the restriction on paginated results) for /api/sensors/1/metrics when hit.

dmahapatro
  • 49,365
  • 7
  • 88
  • 117