toedter / spring-hateoas-jsonapi

A JSON:API media type implementation for Spring HATEOAS
Apache License 2.0
106 stars 15 forks source link

Self-link from demo renders non-functional links #75

Closed paulharkink closed 1 year ago

paulharkink commented 1 year ago

When running the example project on the main branch (latest commit at the time of writing: 41e057ca0e0b3b110710106faa2d68459c03db7f, but the behaviour seems to be consistent with the v2.0.0 tag), the links to individual directors (on the /directors endpoint) contain curly braces where they shouldn't: http://localhost:8080/api/directors/1{?include,fields[directors]} http://localhost:8080/api/directors{?page[number],page[size]} which then leads to this output

// 20230327130921
// http://localhost:8080/api/directors

{
  "jsonapi": {
    "version": "1.1"
  },
  "data": [
    {
      "id": "1",
      "type": "directors",
      "attributes": {
        "name": "Frank Darabont"
      },
      "relationships": {
        "movies": {
          "data": [
            {
              "id": "1",
              "type": "movies"
            },
            {
              "id": "26",
              "type": "movies"
            }
          ]
        }
      },
      "links": {
        "self": "http://localhost:8080/api/directors/1%7B?include,fields%5Bdirectors%5D%7D"
      }
    },
    {
      "id": "2",
      "type": "directors",
      "attributes": {
        "name": "Francis Ford Coppola"
      },
      "relationships": {
        "movies": {
          "data": [
            {
              "id": "2",
              "type": "movies"
            },
            {
              "id": "4",
              "type": "movies"
            },
            {
              "id": "54",
              "type": "movies"
            }
          ]
        }
      },
      "links": {
        "self": "http://localhost:8080/api/directors/2%7B?include,fields%5Bdirectors%5D%7D"
      }
    },
    {
      "id": "3",
      "type": "directors",
      "attributes": {
        "name": "Christopher Nolan"
      },
      "relationships": {
        "movies": {
          "data": [
            {
              "id": "3",
              "type": "movies"
            },
            {
              "id": "13",
              "type": "movies"
            },
            {
              "id": "28",
              "type": "movies"
            },
            {
              "id": "41",
              "type": "movies"
            },
            {
              "id": "52",
              "type": "movies"
            },
            {
              "id": "67",
              "type": "movies"
            },
            {
              "id": "124",
              "type": "movies"
            }
          ]
        }
      },
      "links": {
        "self": "http://localhost:8080/api/directors/3%7B?include,fields%5Bdirectors%5D%7D"
      }
    },
    {
      "id": "4",
      "type": "directors",
      "attributes": {
        "name": "Sidney Lumet"
      },
      "relationships": {
        "movies": {
          "data": [
            {
              "id": "5",
              "type": "movies"
            },
            {
              "id": "221",
              "type": "movies"
            }
          ]
        }
      },
      "links": {
        "self": "http://localhost:8080/api/directors/4%7B?include,fields%5Bdirectors%5D%7D"
      }
    },
    {
      "id": "5",
      "type": "directors",
      "attributes": {
        "name": "Steven Spielberg"
      },
      "relationships": {
        "movies": {
          "data": [
            {
              "id": "6",
              "type": "movies"
            },
            {
              "id": "23",
              "type": "movies"
            },
            {
              "id": "55",
              "type": "movies"
            },
            {
              "id": "117",
              "type": "movies"
            },
            {
              "id": "150",
              "type": "movies"
            },
            {
              "id": "175",
              "type": "movies"
            },
            {
              "id": "206",
              "type": "movies"
            }
          ]
        }
      },
      "links": {
        "self": "http://localhost:8080/api/directors/5%7B?include,fields%5Bdirectors%5D%7D"
      }
    },
    {
      "id": "6",
      "type": "directors",
      "attributes": {
        "name": "Peter Jackson"
      },
      "relationships": {
        "movies": {
          "data": [
            {
              "id": "7",
              "type": "movies"
            },
            {
              "id": "9",
              "type": "movies"
            },
            {
              "id": "14",
              "type": "movies"
            }
          ]
        }
      },
      "links": {
        "self": "http://localhost:8080/api/directors/6%7B?include,fields%5Bdirectors%5D%7D"
      }
    },
    {
      "id": "7",
      "type": "directors",
      "attributes": {
        "name": "Quentin Tarantino"
      },
      "relationships": {
        "movies": {
          "data": [
            {
              "id": "8",
              "type": "movies"
            },
            {
              "id": "56",
              "type": "movies"
            },
            {
              "id": "77",
              "type": "movies"
            },
            {
              "id": "89",
              "type": "movies"
            },
            {
              "id": "151",
              "type": "movies"
            }
          ]
        }
      },
      "links": {
        "self": "http://localhost:8080/api/directors/7%7B?include,fields%5Bdirectors%5D%7D"
      }
    },
    {
      "id": "8",
      "type": "directors",
      "attributes": {
        "name": "Sergio Leone"
      },
      "relationships": {
        "movies": {
          "data": [
            {
              "id": "10",
              "type": "movies"
            },
            {
              "id": "46",
              "type": "movies"
            },
            {
              "id": "81",
              "type": "movies"
            },
            {
              "id": "125",
              "type": "movies"
            }
          ]
        }
      },
      "links": {
        "self": "http://localhost:8080/api/directors/8%7B?include,fields%5Bdirectors%5D%7D"
      }
    },
    {
      "id": "9",
      "type": "directors",
      "attributes": {
        "name": "Robert Zemeckis"
      },
      "relationships": {
        "movies": {
          "data": [
            {
              "id": "11",
              "type": "movies"
            },
            {
              "id": "30",
              "type": "movies"
            }
          ]
        }
      },
      "links": {
        "self": "http://localhost:8080/api/directors/9%7B?include,fields%5Bdirectors%5D%7D"
      }
    },
    {
      "id": "10",
      "type": "directors",
      "attributes": {
        "name": "David Fincher"
      },
      "relationships": {
        "movies": {
          "data": [
            {
              "id": "12",
              "type": "movies"
            },
            {
              "id": "19",
              "type": "movies"
            },
            {
              "id": "181",
              "type": "movies"
            }
          ]
        }
      },
      "links": {
        "self": "http://localhost:8080/api/directors/10%7B?include,fields%5Bdirectors%5D%7D"
      }
    }
  ],
  "links": {
    "self": "http://localhost:8080/api/directors?page%5Bnumber%5D=0&page%5Bsize%5D=10",
    "next": "http://localhost:8080/api/directors?page%5Bnumber%5D=1&page%5Bsize%5D=10",
    "last": "http://localhost:8080/api/directors?page%5Bnumber%5D=17&page%5Bsize%5D=10"
  },
  "meta": {
    "page": {
      "size": 10,
      "totalElements": 175,
      "totalPages": 18,
      "number": 0
    }
  }
}

I must admit I am new to JSON:API or HATEOS, but since directly following those links leads to a '400 bad request' page, and removing them leads to the correct page, to me this looks like a bug.

In DirectorModelAssembler, it looks like some 'templatedLink' is being used, which includes curly braces around the parameters, which are then included in the end result instead of being rendered. In MovieModelAssembler, there is some string replacement happening to filter out the curly brace for the self link, so it looks to be a known issue.

A second bug I encountered in the demo, is that MovieModelAssembler is trying to link to http://localhost:8080/api/movies/1/relationships/directors which is not an implemented endpoint.

These broken examples make it hard to understand how I'm supposed to use this library

toedter commented 1 year ago

Thx for reporting this. The self-link should not be templated, I'll fix this asap.

toedter commented 1 year ago

The relationship links will be fixed in #76.