Entities relationships and actions: how to model a resource creation that depends on another entity?

141 views
Skip to first unread message

Fabio Oliveira

unread,
Jan 11, 2017, 4:11:10 AM1/11/17
to Siren Hypermedia
Hi all,

Thanks all and specially Kevin for this amazing project, I am working in a internal project and we decided to go full power into the direction of a Restful interface, and after some research our specification of choice to help us to model our API is Siren.

But I would like some advice from the experts here. Probably my problem was already solved many times by you so probably you already have some best practices. I have an entity like this:

{
 
"class": [
   
"list"
 
],
 
"entities": [
   
{
     
"class": [
       
"cardSetup"
     
],
     
"rel": [
       
"item"
     
],
     
"properties": {
       
"name": "NFC_virtual_card_CH"
     
},
     
"entities": [
       
{
         
"rel": [
           
"paymentCard"
         
],
         
"href": "/admin/brands/mywirecard2go/model/payment-cards/NFC_virtual_card_CH",
         
"title": "Payment Card"
       
}
     
]
   
}
 
],
 
"actions": [
   
{
     
"name": "create",
     
"method": "POST",
     
"href": "/admin/brands/mywirecard2go/model/card-setups",
     
"type": "application/vnd.wirecard.brand.admin-v1+json"
   
}
 
],
 
"links": [
   
{
     
"rel": [
       
"self"
     
],
     
"href": "/admin/brands/mywirecard2go/model/card-setups"
   
}
 
]
}

Basically as now the entity has a name and an associated entity to it. What I would like to know is how are you guys doing to model the actions to allow, in a machine-understandable way, to create a new entity associated with another already existing entity, how to update, etc...

A friend of us from the siren4j project added some custom attributes to fields, some of them make a lot sense for me, but I would like to discuss how this is seen by the fathers of the specification. For example the "options" attribute or the "optionsURL", see some of the documentation here: https://github.com/eserating/siren4j/wiki/Siren4JAnnotations.

From what I understood I could add in my create action something like that:

...
"fields":[
 
{
   
"name": "paymentCard",
        "optionsURL": "
/admin/brands/mywirecard2go/model/payment-cards"
  }
  ...
]
...

What looks ok-ish, but than how to describe what attribute should be considered the id in the related entity? I can do it by convention, forcing to always have a attribute with the name "id" as the json:api does, or I can add a metadata section to my entity describing that.

But none of than, the fields above and my solution with metadata is described by the specification, so looks like I am taking the wrong direction, can you help me clarifying or giving some examples of similar problems solved by you?

Thanks!




Kevin Swiber

unread,
Jan 23, 2017, 2:05:11 PM1/23/17
to Siren Hypermedia
Hey Fabio,

Thanks for the kind words!  I apologize for the delayed response.

I think there are a few potential solutions here.

I often use application/www-form-urlencoded request bodies, which gel nicely with Siren's HTML5 input field types.  To maintain an association, I often toss a pointer into a hidden field (e.g., { "name": "parent-id", "type": "hidden", "value": 12345 }).  The benefit here is that the client has to do nothing outside of the Siren hypermedia spec.

If you're using a non-default encoding type, you may have to bake that processing instruction into your custom media type documentation (application/vnd.wirecard.brand.admin-v1+json).

In either case, it's helpful to know the association token (perhaps an ID) beforehand.  It seems like options and optionsURL are for providing a "radio button" style selection.  Is that more of what you're going for?

Best Regards,

Kevin

--
You received this message because you are subscribed to the Google Groups "Siren Hypermedia" group.
To unsubscribe from this group and stop receiving emails from it, send an email to siren-hypermed...@googlegroups.com.
To post to this group, send email to siren-hy...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/siren-hypermedia/e4399d04-ad71-46f3-bbf2-5e69b0cc9ce0%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Tom Howard

unread,
Jan 24, 2017, 3:18:27 PM1/24/17
to Siren Hypermedia
Hi Fabio,

I would model each payment card as a factory and have the creation actions on it. e.g.

{
    "class": [
        "paymentCard"
    ],
    "properties": {
        "name": "NFC_virtual_card_CH"
    },
    "actions": [
        {
            "name": "create",
            "method": "POST",
            "href": "/admin/brands/mywirecard2go/model/payment-cards/NFC_virtual_card_CH"
        }
    ],
    "links": [
        {
            "rel": [
                "self"
            ],
            "href": "/admin/brands/mywirecard2go/model/payment-cards/NFC_virtual_card_CH"
        }
    ]
}

I would also model /admin/brands/mywirecard2go/model/payment-cards as a collection, so it would give me a list of payment cards I can create. e.g.

{
    "class": [
        "list"
    ],
    "properties": {
        "count": 1
    },
    "entities": [
        {
            "class": [
                "paymentCard"
            ],
            "rel": [
                "item"
            ],
            "properties": {
                "name": "NFC_virtual_card_CH"
            },
            "actions": [
                {
                    "name": "create",
                    "method": "POST",
                    "href": "/admin/brands/mywirecard2go/model/payment-cards/NFC_virtual_card_CH"
                }
            ],
            "links": [
                {
                    "rel": [
                        "self"
                    ],
                    "href": "/admin/brands/mywirecard2go/model/payment-cards/NFC_virtual_card_CH"
                }
            ]
        }
    ],
    "actions": [
        {
            "name": "search",
            "method": "GET",
            "href": "/admin/brands/mywirecard2go/model/payment-cards",
            "fields": [
                {
                    "name": "q",
                    "type": "text"
                }
            ]
        }
    ],
    "links": [
        {
            "rel": [
                "self"
            ],
            "href": "/admin/brands/mywirecard2go/model/payment-cards"
        },
        {
            "rel": [
                "first"
            ],
            "href": "/admin/brands/mywirecard2go/model/payment-cards"
        },
        {
            "rel": [
                "last"
            ],
            "href": "/admin/brands/mywirecard2go/model/payment-cards"
        }
    ]
}

You could then render the list of cards you can create instances of as a grid, or you could use the search action on a a text box that produces a list of matches as you type. 

Reply all
Reply to author
Forward
0 new messages