I have my Grails Domain classes annotated with @Resource
with the uri specifications in UrlMappings
where I declare the resource nesting. But even though according to https://docs.grails.org/latest/guide/theWebLayer.html#restfulMappings it seems that just declaring this the right way, I should have the correct behavior that I wanted, which is that a URL pattern such as /nesting/1/nested
will list the nested
domain that belonged to the nesting
domain with ID 1
, the observed behavior is that it just lists out all nested
domain objects.
So for that, my workaround is to have a controller implemented that overrides the listResources
to filter the nested
domain by the nesting
domain. But what's weird to me is why I even have to do that at all. The documentation said it defaults to the index
action but said index
action seems to just behave as if it's the index() of nested
(without taking nesting
into account).
My domain entities are WeightSensor
:
@Resource(formats = ['json', 'xml'])
class WeightSensor extends Sensor<WeightData>
{
Set<WeightData> data
static constraints = {
}
}
its superclass Sensor
@Resource(formats = ['json', 'xml'])
class Sensor<T extends SensorData>
{
Set<T> data
static hasMany = [data: SensorData]
String name
static constraints = {
name unique: true
}
}
and WeightData
class WeightData extends SensorData
{
Float weight
static constraints = {
weight nullable: false
}
}
and its superclass SensorData
class SensorData
{
@BindingFormat('yyyy-MM-dd HH:mm:ss.S') // 2019-07-11 22:00:28.909
Date timestamp
static belongsTo = [sensor: Sensor]
static constraints = {
timestamp nullable: false
}
}
In my UrlMappings
I have the following:
"/sensor/weight"(resources: 'weightSensor') {
"/data"(resources: "weightData")
}
My WeightDataController
extends from a SensorDataController
:
class WeightDataController extends SensorDataController<WeightSensor, WeightData>
{
@SuppressWarnings("GroovyUnusedDeclaration")
static responseFormats = ['json', 'xml']
WeightDataController()
{
super(WeightData, WeightSensor, "weightSensorId")
}
}
And SensorDataController in turn extends RestfulController, and overrides the listAllResources
method as below.
import grails.rest.RestfulController
class SensorDataController<S extends Sensor, T extends SensorData> extends RestfulController<T>
{
String idProperty
Class<S> sensorType
@SuppressWarnings("GroovyUnusedDeclaration")
static responseFormats = ['json', 'xml']
protected SensorDataController(Class<T> dataType, Class<S> sensorType, String idProperty)
{
super(dataType)
this.idProperty = idProperty
this.sensorType = sensorType
}
@Override
protected List<T> listAllResources(Map params)
{
Long sensorId = params.get(idProperty) as Long
if (sensorId)
{
resource.withCriteria() {
eq 'sensor.id', sensorId
maxResults params.max ?: 10
firstResult params.offset ?: 0
} as List<T>
}
else
{
super.listAllResources(params)
}
}
}
Note because in order for me to have my WeightDataController
class be used, I needed to remove the @Resource
on top of WeightData
domain entity above, another nice little gem of wisdom I had to discover with trial and error.
I can probably blame this on the fact that the documentation for nested resources seems a bit open to interpretation. But when we see in the documentation a URL like GET books/${bookId}/authors, doesn't that look like it should return the list of Author objects that belongs to the Book instance IDed by bookId?
I know that I'm not alone as I did find this online of someone asking the same question I have - https://gist.github.com/mnellemann/7cfff1c721ef32f0be6c63574795f795 but no one answered them either. I also came across another SO post nested RESTful resources that was abandoned 5 years ago as well.
But 3 people having the same question and no one responding to our questions (I asked mine on the Grails Slack community) usefully because there is a work-around is not acceptable. At the risk of having my question taken down for a slew of different reasons, I question the usefulness of even having the grails nested resource URL mapping in the first place because I could have done everything manually myself without having to "declare" such a nesting in UrlMappings
.
In closing, what I'm trying to find out is whether or not there's more "configuration" I need to do to get Grails nested Resources to behave in the way that I expected, which is how the documentation painted, correctly. Because just doing what was described doesn't get me that.