Darren Guy
Darren Guy

Reputation: 1153

raml 0.8 and using traits for message body

I am using RAML 0.8, and I am trying to use/understand traits

I have an api design that I can see several fields are repeated in the message body for each api call. and my reading of the raml spec, is that as these are repeatable, they should be a candidate for a trait

/kmi/for/{product}:
  uriParameters: 
    product: 
      description: |
        The product that want to be informed about
      required: true
      repeat: false
      type: string
      example: beans
  post:
    description: |
      Used to submit a keep me informed request
    body:
      application/x-www-form-urlencoded:
        formParameters:
          title:
            description: ...
            type: string
            required: false
            repeat: false
            example: Mr
          firstname:
            description: ...
            type: string
            required: true
            repeat: false
            example: John
          lastname:
            description: ...
            type: string
            required: true
            repeat: false
            example: Connor
          emailAddress:
            description: ...
            type: string
            required: true
            repeat: false
            example: [email protected]

Now what I want to do is extract the form fields, title, firstname, lastname, emailAddress into a trait.

I initially tried the following

traits:
  - minimumFormFields:
      title:
        description: ...
        type: string
            ....
      firstname:
        description: ...
        type: string
            ....
      lastname:
        description: ...
        type: string
            ....
      emailAddress:
        description: ...
        type: string
            ....

and added in the trait ( extra fields removed for simplicity )

/kmi/for/{product}:
  post:
    description: |
      ...
    body:
      application/x-www-form-urlencoded:
        formParameters:
          is: [minimumFormFields]

However, that was giving me errors:

RAML 0.8 does not allow using 'title' property within traits

I tried updating the trait to include more from the original definition, but nothing I did appears to work

traits:
  - minimumFormFields:
      application/x-www-form-urlencoded:
        formParameters:
          title:
            description: ...
            type: string
            ....
          firstname:
            description: ...
            type: string
            ....
          lastname:
            description: ...
            type: string
            ....
          emailAddress:
            description: ...
            type: string
            ....

But this gives me the following error

[error] Unknown node: 'application/x-www-form-urlencoded'

If I then include the body in the trait, then I get the following error

[error] Unknown node: '' [error] Unrecognized trait: 'minimumFormFields'.

How can I extract fields that are submitted as part of the message body to a trait?

Our company has standardized on RAML 0.8, so I cannot upgrade to RAML 1.

** * UPDATE 1 * **

Reviewing the comments from Petru Gardea I created a resource type

resourceTypes: 
  minimumFormFields:
    post?:
      body:
        application/x-www-form-urlencoded:
          formParameters:
            title:
              description: ...
              type: string
              required: true
              repeat: false

But I am still getting errors

[error] Node: 'minimumFormFields' should be wrapped in sequence [error] Unknown node: 'minimumFormFields'

Changing to -minimumFormFields:

[error] Node: '-minimumFormFields' should be wrapped in sequence [error] Unknown node: '-minimumFormFields'

Changing to - minimumFormFields:

[error] Unknown node: ''

I am using mulesoft.com for editing my RAML

Upvotes: 1

Views: 508

Answers (1)

Petru Gardea
Petru Gardea

Reputation: 21658

I don't think you can achieve what you want with traits. Instead, you need to employ resourceTypes.

This is a possible approach, showing you how it could work. The meaning of the resources is as follows:

  • /kmi/test/1: Even though it is of the minimumFormFields type, since it doesn't define a post, it won't "inherit" it from the resourceType (notice the ? after post, which makes it optional);
  • /kmi/test/2: defined as a reference, as per your original post
  • /kmi/test/3: shows that you can even override/add from the "base" type.
  • /kmi/for/{product}: clean setup, as per your requirements.

It always help to have the ability to "visualize" the "resolved" contract. A RAML parser should do this for you. The screenshots following the RAML should be self explanatory.

#%RAML 0.8
---
title: Sample
resourceTypes: 
  - minimumFormFields:
      post?:      
        body:
          application/x-www-form-urlencoded:   
            formParameters:
              title:
                description: ...
                type: string
                required: false
                repeat: false
                example: Mr
              firstname:
                description: ...
                type: string
                required: true
                repeat: false
                example: John
              lastname:
                description: ...
                type: string
                required: true
                repeat: false
                example: Connor
              emailAddress:
                description: ...
                type: string
                required: true
                repeat: false
                example: [email protected]            

/kmi/test/1:
  type: minimumFormFields
  uriParameters: 
    product: 
      description: |
        The product that want to be informed about
      required: true
      repeat: false
      type: string
      example: beans
  get:
    description: |
      Doens't show a POST
/kmi/test/2:
  post:
    description: |
      Used to submit a keep me informed request
    body:
      application/x-www-form-urlencoded:
        formParameters:
          title:
            description: ...
            type: string
            required: false
            repeat: false
            example: Mr
          firstname:
            description: ...
            type: string
            required: true
            repeat: false
            example: John
          lastname:
            description: ...
            type: string
            required: true
            repeat: false
            example: Connor
          emailAddress:
            description: ...
            type: string
            required: true
            repeat: false
            example: [email protected]        
/kmi/for/{product}:
  type: minimumFormFields
  uriParameters: 
    product: 
      description: |
        The product that want to be informed about
      required: true
      repeat: false
      type: string
      example: beans
  post:
    description: |
      Used to submit a keep me informed request
/kmi/test/3:
  type: minimumFormFields
  uriParameters: 
    product: 
      description: |
        The product that want to be informed about
      required: true
      repeat: false
      type: string
      example: beans
  post:
    description: |
      Used to submit a keep me informed request      
    body:
      application/x-www-form-urlencoded:
        formParameters:
          anotherThing:
            description: ...
            type: string
            required: false
            repeat: false
            example: Mr
          emailAddress:
            description: This looks better
            type: string
            required: true
            repeat: false
            example: [email protected]

Test 1: POST is removed, showing only a GET

enter image description here

Test 2: The "inlined" way.

enter image description here

Test 3: The "reused" way.

enter image description here

Test 4: The "overridden" way.

enter image description here

Upvotes: 0

Related Questions