spring-hateoas.md 94.8 KB
Newer Older
茶陵後's avatar
茶陵後 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146
# Spring HATEOAS - Reference Documentation

## 1. Preface

### 1.1. Migrating to Spring HATEOAS 1.0

For 1.0 we took the chance to re-evaluate some of the design and package structure choices we had made for the 0.x branch.
There had been an incredible amount of feedback on it and the major version bump seemed to be the most natural place to refactor those.

#### 1.1.1. The changes

The biggest changes in package structure were driven by the introduction of a hypermedia type registration API to support additional media types in Spring HATEOAS.
This lead to the clear separation of client and server APIs (packages named respectively) as well as media type implementations in the package `mediatype`.

The easiest way to get your code base upgraded to the new API is by using the [migration script](#migrate-to-1.0.script).
Before we jump to that, here are the changes at a quick glance.

##### Representation models

The `ResourceSupport`/`Resource`/`Resources`/`PagedResources` group of classes never really felt appropriately named.
After all, these types do not actually manifest resources but rather representation models that can be enriched with hypermedia information and affordances.
Here’s how new names map to the old ones:

* `ResourceSupport` is now `RepresentationModel`

* `Resource` is now `EntityModel`

* `Resources` is now `CollectionModel`

* `PagedResources` is now `PagedModel`

Consequently, `ResourceAssembler` has been renamed to `RepresentationModelAssembler` and its methods `toResource(…)` and `toResources(…)` have been renamed to `toModel(…)` and `toCollectionModel(…)` respectively.
Also the name changes have been reflected in the classes contained in `TypeReferences`.

* `RepresentationModel.getLinks()` now exposes a `Links` instance (over a `List<Link>`) as that exposes additional API to concatenate and merge different `Links` instances using various strategies.
  Also it has been turned into a self-bound generic type to allow the methods that add links to the instance return the instance itself.

* The `LinkDiscoverer` API has been moved to the `client` package.

* The `LinkBuilder` and `EntityLinks` APIs have been moved to the `server` package.

* `ControllerLinkBuilder` has been moved into `server.mvc` and deprecated to be replaced by `WebMvcLinkBuilder`.

* `RelProvider` has been renamed to `LinkRelationProvider` and returns `LinkRelation` instances instead of `String`s.

* `VndError` has been moved to the `mediatype.vnderror` package.

#### 1.1.2. The migration script

You can find [a script](https://github.com/spring-projects/spring-hateoas/tree/master/etc) to run from your application root that will update all import statements and static method references to Spring HATEOAS types that moved in our source code repository.
Simply download that, run it from your project root.
By default it will inspect all Java source files and replace the legacy Spring HATEOAS type references with the new ones.

Example 1. Sample application of the migration script

```
$ ./migrate-to-1.0.sh

Migrating Spring HATEOAS references to 1.0 for files : *.java

Adapting ./src/main/java/…


Done!
```

Note that the script will not necessarily be able to entirely fix all changes, but it should cover the most important refactorings.

Now verify the changes made to the files in your favorite Git client and commit as appropriate.
In case you find method or type references unmigrated, please open a ticket in out issue tracker.

#### 1.1.3. Migrating from 1.0 M3 to 1.0 RC1

* `Link.andAffordance(…)` taking Affordance details have been moved to `Affordances`. To manually build up `Affordance` instances now use `Affordances.of(link).afford(…)`. Also note the new `AffordanceBuilder` type exposed from `Affordances` for fluent usage. See [Affordances](#server.affordances) for details.

* `AffordanceModelFactory.getAffordanceModel(…)` now receives `InputPayloadMetadata` and `PayloadMetadata` instances instead of `ResolvableType`s to allow non-type-based implementations. Custom media type implementations have to be adapted to that accordingly.

* HAL Forms now does not render property attributes if their value adheres to what’s defined as default in the spec. I.e. if previously `required` was explicitly set to `false`, we now just omit the entry for `required`.
  We also now only force them to be non-required for templates that use `PATCH` as the HTTP method.

## 2. Fundamentals

This section covers the basics of Spring HATEOAS and its fundamental domain abstractions.

### 2.1. Links

The fundamental idea of hypermedia is to enrich the representation of a resource with hypermedia elements.
The simplest form of that are links.
They indicate a client that it can navigate to a certain resource.
The semantics of a related resource are defined in a so-called link relation.
You might have seen this in the header of an HTML file already:

Example 2. A link in an HTML document

```
<link href="theme.css" rel="stylesheet" type="text/css" />
```

As you can see the link points to a resource `theme.css` and indicates that it is a style sheet.
Links often carry additional information, like the media type that the resource pointed to will return.
However, the fundamental building blocks of a link are its reference and relation.

Spring HATEOAS lets you work with links through its immutable `Link` value type.
Its constructor takes both a hypertext reference and a link relation, the latter being defaulted to the IANA link relation `self`.
Read more on the latter in [Link relations](#fundamentals.link-relations).

Example 3. Using links

```
Link link = Link.of("/something");
assertThat(link.getHref()).isEqualTo("/something");
assertThat(link.getRel()).isEqualTo(IanaLinkRelations.SELF);

link = Link.of("/something", "my-rel");
assertThat(link.getHref()).isEqualTo("/something");
assertThat(link.getRel()).isEqualTo(LinkRelation.of("my-rel"));
```

`Link` exposes other attributes as defined in [RFC-8288](https://tools.ietf.org/html/rfc8288).
You can set them by calling the corresponding wither method on a `Link` instance.

Find more information on how to create links pointing to Spring MVC and Spring WebFlux controllers in [ Building links in Spring MVC](#server.link-builder.webmvc) and [Building links in Spring WebFlux](#server.link-builder.webflux).

### 2.2. URI templates

For a Spring HATEOAS `Link`, the hypertext reference can not only be a URI, but also a URI template according to [RFC-6570](https://tools.ietf.org/html/rfc6570).
A URI template contains so-called template variables and allows expansion of these parameters.
This allows clients to turn parameterized templates into URIs without having to know about the structure of the final URI, it only needs to know about the names of the variables.

Example 4. Using links with templated URIs

```
Link link = Link.of("/{segment}/something{?parameter}");
assertThat(link.isTemplated()).isTrue(); (1)
assertThat(link.getVariableNames()).contains("segment", "parameter"); (2)

Map<String, Object> values = new HashMap<>();
values.put("segment", "path");
values.put("parameter", 42);

assertThat(link.expand(values).getHref()) (3)
    .isEqualTo("/path/something?parameter=42");
```

|**1**|The `Link` instance indicates that is templated, i.e. it contains a URI template.|
|-----|---------------------------------------------------------------------------------|
|**2**|              It exposes the parameters contained in the template.               |
|**3**|                     It allows expansion of the parameters.                      |

URI templates can be constructed manually and template variables added later on.

Example 5. Working with URI templates

```
UriTemplate template = UriTemplate.of("/{segment}/something")
  .with(new TemplateVariable("parameter", VariableType.REQUEST_PARAM);

assertThat(template.toString()).isEqualTo("/{segment}/something{?parameter}");
```

### 2.3. Link relations

To indicate the relationship of the target resource to the current one so-called link relations are used.
Spring HATEOAS provides a `LinkRelation` type to easily create `String`-based instances of it.

#### 2.3.1. IANA link relations

The Internet Assigned Numbers Authority contains a set of [predefined link relations](https://www.iana.org/assignments/link-relations/link-relations.xhtml).
They can be referred to via `IanaLinkRelations`.

Example 6. Using IANA link relations

```
Link link = Link.of("/some-resource"), IanaLinkRelations.NEXT);

assertThat(link.getRel()).isEqualTo(LinkRelation.of("next"));
assertThat(IanaLinkRelation.isIanaRel(link.getRel())).isTrue();
```

###  Representation models

To easily create hypermedia enriched representations, Spring HATEOAS provides a set of classes with `RepresentationModel` at their root.
It’s basically a container for a collection of `Link`s and has convenient methods to add those to the model.
The models can later be rendered into various media type formats that will define how the hypermedia elements look in the representation.
For more information on this, have a look at [Media types](#mediatypes).

Example 7. The `RepresentationModel` class hierarchy

<img alt="diagram classes" src="https://docs.spring.io/spring-hateoas/docs/current/reference/html/images/diagram-classes.svg" height="120" width="632" />

The default way to work with a `RepresentationModel` is to create a subclass of it to contain all the properties the representation is supposed to contain, create instances of that class, populate the properties and enrich it with links.

Example 8. A sample representation model type

```
class PersonModel extends RepresentationModel<PersonModel> {

  String firstname, lastname;
}
```

The generic self-typing is necessary to let `RepresentationModel.add(…)` return instances of itself.
The model type can now be used like this:

Example 9. Using the person representation model

```
PersonModel model = new PersonModel();
model.firstname = "Dave";
model.lastname = "Matthews";
model.add(Link.of("https://myhost/people/42"));
```

If you returned such an instance from a Spring MVC or WebFlux controller and the client sent an `Accept` header set to `application/hal+json`, the response would look as follows:

Example 10. The HAL representation generated for the person representation model

```
{
  "_links" : {
    "self" : {
      "href" : "https://myhost/people/42"
    }
  },
  "firstname" : "Dave",
  "lastname" : "Matthews"
}
```

#### 2.4.1. Item resource representation model

For a resource that’s backed by a singular object or concept, a convenience `EntityModel` type exists.
Instead of creating a custom model type for each concept, you can just reuse an already existing type and wrap instances of it into the `EntityModel`.

Example 11. Using `EntityModel` to wrap existing objects

```
Person person = new Person("Dave", "Matthews");
EntityModel<Person> model = EntityModel.of(person);
```

#### 2.4.2. Collection resource representation model

For resources that are conceptually collections, a `CollectionModel` is available.
Its elements can either be simple objects or `RepresentationModel` instances in turn.

Example 12. Using `CollectionModel` to wrap a collection of existing objects

```
Collection<Person> people = Collections.singleton(new Person("Dave", "Matthews"));
CollectionModel<Person> model = CollectionModel.of(people);
```

## 3. Server-side support

###  Building links in Spring MVC

Now we have the domain vocabulary in place, but the main challenge remains: how to create the actual URIs to be wrapped into `Link` instances in a less fragile way. Right now, we would have to duplicate URI strings all over the place. Doing so is brittle and unmaintainable.

Assume you have your Spring MVC controllers implemented as follows:

```
@Controller
class PersonController {

  @GetMapping("/people")
  HttpEntity<PersonModel> showAll() { … }

  @GetMapping(value = "/{person}", method = RequestMethod.GET)
  HttpEntity<PersonModel> show(@PathVariable Long person) { … }
}
```

We see two conventions here. The first is a collection resource that is exposed through `@GetMapping` annotation of the controller method, with individual elements of that collection exposed as direct sub resources. The collection resource might be exposed at a simple URI (as just shown) or more complex ones (such as `/people/{id}/addresses`). Suppose you would like to link to the collection resource of all people. Following the approach from above would cause two problems:

* To create an absolute URI, you would need to look up the protocol, hostname, port, servlet base, and other values. This is cumbersome and requires ugly manual string concatenation code.

* You probably do not want to concatenate the `/people` on top of your base URI, because you would then have to maintain the information in multiple places. If you change the mapping, you then have to change all the clients pointing to it.

Spring HATEOAS now provides a `WebMvcLinkBuilder` that lets you create links by pointing to controller classes.
The following example shows how to do so:

```
import static org.sfw.hateoas.server.mvc.WebMvcLinkBuilder.*;

Link link = linkTo(PersonController.class).withRel("people");

assertThat(link.getRel()).isEqualTo(LinkRelation.of("people"));
assertThat(link.getHref()).endsWith("/people");
```

The `WebMvcLinkBuilder` uses Spring’s `ServletUriComponentsBuilder` under the hood to obtain the basic URI information from the current request. Assuming your application runs at `[localhost:8080/your-app](http://localhost:8080/your-app)`, this is exactly the URI on top of which you are constructing additional parts. The builder now inspects the given controller class for its root mapping and thus ends up with `[localhost:8080/your-app/people](http://localhost:8080/your-app/people)`. You can also build more nested links as well.
The following example shows how to do so:

```
Person person = new Person(1L, "Dave", "Matthews");
//                 /person                 /     1
Link link = linkTo(PersonController.class).slash(person.getId()).withSelfRel();
assertThat(link.getRel(), is(IanaLinkRelation.SELF.value()));
assertThat(link.getHref(), endsWith("/people/1"));
```

The builder also allows creating URI instances to build up (for example, response header values):

```
HttpHeaders headers = new HttpHeaders();
headers.setLocation(linkTo(PersonController.class).slash(person).toUri());

return new ResponseEntity<PersonModel>(headers, HttpStatus.CREATED);
```

#### 3.1.1. Building links that point to methods

You can even build links that point to methods or create dummy controller method invocations.
The first approach is to hand a `Method` instance to the `WebMvcLinkBuilder`.
The following example shows how to do so:

```
Method method = PersonController.class.getMethod("show", Long.class);
Link link = linkTo(method, 2L).withSelfRel();

assertThat(link.getHref()).endsWith("/people/2"));
```

This is still a bit dissatisfying, as we have to first get a `Method` instance, which throws an exception and is generally quite cumbersome. At least we do not repeat the mapping. An even better approach is to have a dummy method invocation of the target method on a controller proxy, which we can create by using the `methodOn(…)` helper.
The following example shows how to do so:

```
Link link = linkTo(methodOn(PersonController.class).show(2L)).withSelfRel();

assertThat(link.getHref()).endsWith("/people/2");
```

`methodOn(…)` creates a proxy of the controller class that records the method invocation and exposes it in a proxy created for the return type of the method. This allows the fluent expression of the method for which we want to obtain the mapping. However, there are a few constraints on the methods that can be obtained by using this technique:

* The return type has to be capable of proxying, as we need to expose the method invocation on it.

* The parameters handed into the methods are generally neglected (except the ones referred to through `@PathVariable`, because they make up the URI).

### 3.2. Building links in Spring WebFlux

TODO

### 3.3. Affordances

>
>
>
>
> The affordances of the environment are what it offers …​ what it provides or furnishes, either for good or ill. The verb 'to afford' is found in the dictionary, but the noun 'affordance' is not. I have made it up.
>
>
>
>

— James J. Gibson  

> The Ecological Approach to Visual Perception (page 126)

REST-based resources provide not just data but controls.
The last ingredient to form a flexible service are detailed **affordances** on how to use the various controls.
Because affordances are associated with links, Spring HATEOAS provides an API to attach as many related methods as needed to a link.
Just as you can create links by pointing to Spring MVC controller methods (see [ Building links in Spring MVC](#server.link-builder.webmvc) for details) you …​

The following code shows how to take a **self** link and associate two more affordances:

Example 13. Connecting affordances to `GET /employees/{id}`

```
@GetMapping("/employees/{id}")
public EntityModel<Employee> findOne(@PathVariable Integer id) {

  Class<EmployeeController> controllerClass = EmployeeController.class;

  // Start the affordance with the "self" link, i.e. this method.
  Link findOneLink = linkTo(methodOn(controllerClass).findOne(id)).withSelfRel(); (1)

  // Return the affordance + a link back to the entire collection resource.
  return EntityModel.of(EMPLOYEES.get(id), //
      findOneLink //
          .andAffordance(afford(methodOn(controllerClass).updateEmployee(null, id))) (2)
          .andAffordance(afford(methodOn(controllerClass).partiallyUpdateEmployee(null, id)))); (3)
}
```

|**1**|                     Create the **self** link.                      |
|-----|--------------------------------------------------------------------|
|**2**|    Associate the `updateEmployee` method with the `self` link.     |
|**3**|Associate the `partiallyUpdateEmployee` method with the `self` link.|

Using `.andAffordance(afford(…​))`, you can use the controller’s methods to connect a `PUT` and a `PATCH` operation to a `GET` operation.
Imagine that the related methods **afforded** above look like this:

Example 14. `updateEmpoyee` method that responds to `PUT /employees/{id}`

```
@PutMapping("/employees/{id}")
public ResponseEntity<?> updateEmployee( //
    @RequestBody EntityModel<Employee> employee, @PathVariable Integer id)
```

Example 15. `partiallyUpdateEmployee` method that responds to `PATCH /employees/{id}`

```
@PatchMapping("/employees/{id}")
public ResponseEntity<?> partiallyUpdateEmployee( //
    @RequestBody EntityModel<Employee> employee, @PathVariable Integer id)
```

Pointing to those methods using the `afford(…)` methods will cause Spring HATEOAS to analyze the request body and response types and capture metadata to allow different media type implementations to use that information to translate that into descriptions of the input and outputs.

#### 3.3.1. Building affordances manually

While the primary way to register affordances for a link, it might be necessary to build some of them manually.
This can be achieved by using the `Affordances` API:

Example 16. Using the `Affordances` API to manually register affordances

```
var methodInvocation = methodOn(EmployeeController.class).all();

var link = Affordances.of(linkTo(methodInvocation).withSelfRel()) (1)

    .afford(HttpMethod.POST) (2)
    .withInputAndOutput(Employee.class) //
    .withName("createEmployee") //

    .andAfford(HttpMethod.GET) (3)
    .withOutput(Employee.class) //
    .addParameters(//
        QueryParameter.optional("name"), //
        QueryParameter.optional("role")) //
    .withName("search") //

    .toLink();
```

|**1**|                                                                                                                      You start by creating an instance of `Affordances` from a `Link` instance creating the context for describing the affordances.                                                                                                                       |
|-----|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|**2**|Each affordance starts with the HTTP method it’s supposed to support. We then register a type as payload description and name the affordance explicitly. The latter can be omitted and a default name will be derived from the HTTP method and input type name. This effectively creates the same affordance as the pointer to `EmployeeController.newEmployee(…)` created.|
|**3**|                                                                         The next affordance is built to reflect what’s happening for the pointer to `EmployeeController.search(…)`. Here we define `Employee` to be the model for the response created and explicitly register `QueryParameter`s.                                                                         |

Affordances are backed by media type specific affordance models that translate the general affordance metadata into specific representations.
Please make sure to check the section on affordances in the [Media types](#mediatypes) section to find more details about how to control the exposure of that metadata.

### 3.4. Forwarded header handling

[RFC-7239 forwarding headers](https://tools.ietf.org/html/rfc7239) are most commonly used when your application is behind a proxy, behind a load balancer, or in the cloud.
The node that actually receives the web request is part of the infrastructure, and *forwards* the request to your application.

Your application may be running on `localhost:8080`, but to the outside world you’re expected to be at `reallycoolsite.com` (and on the web’s standard port 80).
By having the proxy include extra headers (which many already do), Spring HATEOAS can generate links properly as it uses Spring Framework functionality to obtain the base URI of the original request.

|   |Anything that can change the root URI based on external inputs must be properly guarded.<br/>That’s why, by default, forwarded header handling is **disabled**.<br/>You MUST enable it to be operational.<br/>If you are deploying to the cloud or into a configuration where you control the proxies and load balancers, then you’ll certainly want to use this feature.|
|---|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

To enable forwarded header handling you need to register Spring’s `ForwardedHeaderFilter` for Spring MVC (details [here](https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#filters-forwarded-headers)) or `ForwardedHeaderTransformer` for Spring WebFlux (details [here](https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html#webflux-forwarded-headers)) in your application.
In a Spring Boot application those components can be simply declared as Spring beans as described [here](https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-developing-web-applications.html#boot-features-embedded-container-servlets-filters-listeners-beans).

Example 17. Registering a `ForwardedHeaderFilter`

```
@Bean
ForwardedHeaderFilter forwardedHeaderFilter() {
    return new ForwardedHeaderFilter();
}
```

This will create a servlet filter that processes all the `X-Forwarded-…` headers.
And it will register it properly with the servlet handlers.

For a Spring WebFlux application, the reactive counterpart is `ForwardedHeaderTransformer`:

Example 18. Registering a `ForwardedHeaderTransformer`

```
@Bean
ForwardedHeaderTransformer forwardedHeaderTransformer() {
    return new ForwardedHeaderTransformer();
}
```

This will create a function that transforms reactive web requests, processing `X-Forwarded-…` headers.
And it will register it properly with WebFlux.

With configuration as shown above in place, a request passing `X-Forwarded-…` headers will see those reflected in the links generated:

Example 19. A request using `X-Forwarded-…` headers

```
curl -v localhost:8080/employees \
    -H 'X-Forwarded-Proto: https' \
    -H 'X-Forwarded-Host: example.com' \
    -H 'X-Forwarded-Port: 9001'
```

Example 20. The corresponding response with the links generated to consider those headers

```
{
  "_embedded": {
    "employees": [
      {
        "id": 1,
        "name": "Bilbo Baggins",
        "role": "burglar",
        "_links": {
          "self": {
            "href": "https://example.com:9001/employees/1"
          },
          "employees": {
            "href": "https://example.com:9001/employees"
          }
        }
      }
    ]
  },
  "_links": {
    "self": {
      "href": "https://example.com:9001/employees"
    },
    "root": {
      "href": "https://example.com:9001"
    }
  }
}
```

###  Using the EntityLinks interface

|   |`EntityLinks` and its various implementations are NOT currently provided out-of-the-box for Spring WebFlux applications.<br/>The contract defined in the `EntityLinks` SPI was originally aimed at Spring Web MVC and doesn’t consider Reactor types.<br/>Developing a comparable contract that supports reactive programming is still in progress.|
|---|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

So far, we have created links by pointing to the web framework implementations (that is, the Spring MVC controllers) and inspected the mapping.
In many cases, these classes essentially read and write representations backed by a model class.

The `EntityLinks` interface now exposes an API to look up a `Link` or `LinkBuilder` based on the model types.
The methods essentially return links that point either to the collection resource (such as `/people`) or to an item resource (such as `/people/1`).
The following example shows how to use `EntityLinks`:

```
EntityLinks links = …;
LinkBuilder builder = links.linkFor(Customer.class);
Link link = links.linkToItemResource(Customer.class, 1L);
```

`EntityLinks` is available via dependency injection by activating `@EnableHypermediaSupport` in your Spring MVC configuration.
This will cause a variety of default implementations of `EntityLinks` being registered.
The most fundamental one is `ControllerEntityLinks` that inspects SpringMVC controller classes.
If you want to register your own implementation of `EntityLinks`, check out [this section](#server.entity-links.spi).

#### 3.5.1. EntityLinks based on Spring MVC controllers

Activating entity links functionality causes all the Spring MVC controllers available in the current `ApplicationContext` to be inspected for the `@ExposesResourceFor(…)` annotation.
The annotation exposes which model type the controller manages.
Beyond that, we assume that you adhere to the following URI mapping setup and conventions:

* A type level `@ExposesResourceFor(…)` declaring which entity type the controller exposes collection and item resources for.

* A class level base mapping that represents the collection resource.

* An additional method level mapping that extends the mapping to append an identifier as additional path segment.

The following example shows an implementation of an `EntityLinks`-capable controller:

```
@Controller
@ExposesResourceFor(Order.class) (1)
@RequestMapping("/orders") (2)
class OrderController {

  @GetMapping (3)
  ResponseEntity orders(…) { … }

  @GetMapping("{id}") (4)
  ResponseEntity order(@PathVariable("id") … ) { … }
}
```

|**1**|                       The controller indicates it’s exposing collection and item resources for the entity `Order`.                       |
|-----|------------------------------------------------------------------------------------------------------------------------------------------|
|**2**|                                            Its collection resource is exposed under `/orders`                                            |
|**3**|             That collection resource can handle `GET` requests. Add more methods for other HTTP methods at your convenience.             |
|**4**|An additional controller method to handle a subordinate resource taking a path variable to expose an item resource, i.e. a single `Order`.|

With this in place, when you enable `EntityLinks` `@EnableHypermediaSupport` in your Spring MVC configuration, you can create links to the controller as follows:

```
@Controller
class PaymentController {

  private final EntityLinks entityLinks;

  PaymentController(EntityLinks entityLinks) { (1)
    this.entityLinks = entityLinks;
  }

  @PutMapping(…)
  ResponseEntity payment(@PathVariable Long orderId) {

    Link link = entityLinks.linkToItemResource(Order.class, orderId); (2)

  }
}
```

|**1**|Inject `EntityLinks` made available by `@EnableHypermediaSupport` in your configuration.|
|-----|----------------------------------------------------------------------------------------|
|**2**|  Use the APIs to build links by using the entity types instead of controller classes.  |

As you can see, you can refer to resources managing `Order` instances without referring to `OrderController` explicitly.

#### 3.5.2. EntityLinks API in detail

Fundamentally, `EntityLinks` allows to build `LinkBuilder`s and `Link` instances to collection and item resources of an entity type.
Methods starting with `linkFor…` will produce `LinkBuilder` instances for you to extend and augment with additional path segments, parameters, etc.
Methods starting with `linkTo` produce fully prepared `Link` instances.

While for collection resources providing an entity type is sufficient, links to item resources will need an identifier provided.
This usually looks like this:

Example 21. Obtaining a link to an item resource

```
entityLinks.linkToItemResource(order, order.getId());
```

If you find yourself repeating those method calls the identifier extraction step can be pulled out into a reusable `Function` to be reused throughout different invocations:

```
Function<Order, Object> idExtractor = Order::getId; (1)

entityLinks.linkToItemResource(order, idExtractor); (2)
```

|**1**|The identifier extraction is externalized so that it can be held in a field or constant.|
|-----|----------------------------------------------------------------------------------------|
|**2**|                          The link lookup using the extractor.                          |

##### TypedEntityLinks

As controller implementations are often grouped around entity types, you’ll very often find yourself using the same extractor function (see [EntityLinks API in detail](#server.entity-links.api) for details) all over the controller class.
We can centralize the identifier extraction logic even more by obtaining a `TypedEntityLinks` instance providing the extractor once, so that the actual lookups don’t have to deal with the extraction anymore at all.

Example 22. Using TypedEntityLinks

```
class OrderController {

  private final TypedEntityLinks<Order> links;

  OrderController(EntityLinks entityLinks) { (1)
    this.links = entityLinks.forType(Order::getId); (2)
  }

  @GetMapping
  ResponseEntity<Order> someMethod(…) {

    Order order = … // lookup order

    Link link = links.linkToItemResource(order); (3)
  }
}
```

|**1**|                               Inject an `EntityLinks` instance.                                |
|-----|------------------------------------------------------------------------------------------------|
|**2**|Indicate you’re going to look up `Order` instances with a certain identifier extractor function.|
|**3**|                 Look up item resource links based on a sole `Order` instance.                  |

#### 3.5.3. EntityLinks as SPI

The `EntityLinks` instance created by `@EnableHypermediaSupport` is of type `DelegatingEntityLinks` which will in turn pick up all other `EntityLinks` implementations available as beans in the `ApplicationContext`.
It’s registered as primary bean so that it’s always the sole injection candidate when you inject `EntityLinks` in general.`ControllerEntityLinks` is the default implementation that will be included in the setup, but users are free to implement and register their own implementations.
Making those available to the `EntityLinks` instance available for injection is a matter of registering your implementation as Spring bean.

Example 23. Declaring a custom EntityLinks implementation

```
@Configuration
class CustomEntityLinksConfiguration {

  @Bean
  MyEntityLinks myEntityLinks(…) {
    return new MyEntityLinks(…);
  }
}
```

An example for the extensibility of this mechanism is Spring Data REST’s [`RepositoryEntityLinks`](https://github.com/spring-projects/spring-data-rest/blob/3a0cba94a2cc8739375ecf24086da2f7c3bbf038/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/support/RepositoryEntityLinks.java), which uses the repository mapping information to create links pointing to resources backed by Spring Data repositories.
At the same time, it even exposes additional lookup methods for other types of resources.
If you want to make use of these, simply inject `RepositoryEntityLinks` explicitly.

###  Representation model assembler

As the mapping from an entity to a representation model must be used in multiple places, it makes sense to create a dedicated class responsible for doing so. The conversion contains very custom steps but also a few boilerplate steps:

1. Instantiation of the model class

2. Adding a link with a `rel` of `self` pointing to the resource that gets rendered.

Spring HATEOAS now provides a `RepresentationModelAssemblerSupport` base class that helps reduce the amount of code you need to write.
The following example shows how to use it:

```
class PersonModelAssembler extends RepresentationModelAssemblerSupport<Person, PersonModel> {

  public PersonModelAssembler() {
    super(PersonController.class, PersonModel.class);
  }

  @Override
  public PersonModel toModel(Person person) {

    PersonModel resource = createResource(person);
    // … do further mapping
    return resource;
  }
}
```

|   |`createResource(…​)` is code you write to instantiate a `PersonModel` object given a `Person` object. It should only focus on setting attributes, not populating `Links`.|
|---|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

Setting the class up as we did in the preceding example gives you the following benefits:

* There are a handful of `createModelWithId(…)` methods that let you create an instance of the resource and have a `Link` with a rel of `self` added to it. The href of that link is determined by the configured controller’s request mapping plus the ID of the entity (for example, `/people/1`).

* The resource type gets instantiated by reflection and expects a no-arg constructor. If you want to use a dedicated constructor or avoid the reflection performance overhead, you can override `instantiateModel(…)`.

You can then use the assembler to either assemble a `RepresentationModel` or a `CollectionModel`.
The following example creates a `CollectionModel` of `PersonModel` instances:

```
Person person = new Person(…);
Iterable<Person> people = Collections.singletonList(person);

PersonModelAssembler assembler = new PersonModelAssembler();
PersonModel model = assembler.toModel(person);
CollectionModel<PersonModel> model = assembler.toCollectionModel(people);
```

### 3.7. Representation Model Processors

Sometimes you need to tweak and adjust hypermedia representations after they have been [assembled](#server.representation-model-assembler).

A perfect example is when you have a controller that deals with order fulfillment, but you need to add links related to making payments.

Imagine having your ordering system producing this type of hypermedia:

```
{
  "orderId" : "42",
  "state" : "AWAITING_PAYMENT",
  "_links" : {
    "self" : {
      "href" : "http://localhost/orders/999"
    }
  }
}
```

You wish to add a link so the client can make payment, but don’t want to mix details about your `PaymentController` into
the `OrderController`.

Instead of polluting the details of your ordering system, you can write a `RepresentationModelProcessor` like this:

```
public class PaymentProcessor implements RepresentationModelProcessor<EntityModel<Order>> { (1)

  @Override
  public EntityModel<Order> process(EntityModel<Order> model) {

    model.add( (2)
        Link.of("/payments/{orderId}").withRel(LinkRelation.of("payments")) //
            .expand(model.getContent().getOrderId()));

    return model; (3)
  }
}
```

|**1**|     This processor will only be applied to `EntityModel<Order>` objects.      |
|-----|-------------------------------------------------------------------------------|
|**2**| Manipulate the existing `EntityModel` object by adding an unconditional link. |
|**3**|Return the `EntityModel` so it can be serialized into the requested media type.|

Register the processor with your application:

```
@Configuration
public class PaymentProcessingApp {

  @Bean
  PaymentProcessor paymentProcessor() {
    return new PaymentProcessor();
  }
}
```

Now when you issue a hypermedia respresentation of an `Order`, the client receives this:

```
{
  "orderId" : "42",
  "state" : "AWAITING_PAYMENT",
  "_links" : {
    "self" : {
      "href" : "http://localhost/orders/999"
    },
    "payments" : { (1)
      "href" : "/payments/42" (2)
    }
  }
}
```

|**1**|You see the `LinkRelation.of("payments")` plugged in as this link’s relation.|
|-----|-----------------------------------------------------------------------------|
|**2**|                   The URI was provided by the processor.                    |

This example is quite simple, but you can easily:

* Use `WebMvcLinkBuilder` or `WebFluxLinkBuilder` to construct a dynamic link to your `PaymentController`.

* Inject any services needed to conditionally add other links (e.g. `cancel`, `amend`) that are driven by state.

* Leverage cross cutting services like Spring Security to add, remove, or revise links based upon the current user’s context.

Also, in this example, the `PaymentProcessor` alters the provided `EntityModel<Order>`. You also have the power to*replace* it with another object. Just be advised the API requires the return type to equal the input type.

###  Using the `LinkRelationProvider` API

When building links, you usually need to determine the relation type to be used for the link. In most cases, the relation type is directly associated with a (domain) type. We encapsulate the detailed algorithm to look up the relation types behind a `LinkRelationProvider` API that lets you determine the relation types for single and collection resources. The algorithm for looking up the relation type follows:

1. If the type is annotated with `@Relation`, we use the values configured in the annotation.

2. If not, we default to the uncapitalized simple class name plus an appended `List` for the collection `rel`.

3. If the [EVO inflector](https://github.com/atteo/evo-inflector) JAR is in the classpath, we use the plural of the single resource `rel` provided by the pluralizing algorithm.

4. `@Controller` classes annotated with `@ExposesResourceFor` (see [ Using the EntityLinks interface](#server.entity-links) for details) transparently look up the relation types for the type configured in the annotation, so that you can use `LinkRelationProvider.getItemResourceRelFor(MyController.class)` and get the relation type of the domain type exposed.

A `LinkRelationProvider` is automatically exposed as a Spring bean when you use `@EnableHypermediaSupport`. You can plug in custom providers by implementing the interface and exposing them as Spring beans in turn.

## 4. Media types

### 4.1. HAL – Hypertext Application Language

[JSON Hypertext Application Language](https://tools.ietf.org/html/draft-kelly-json-hal-08) or HAL is one of the simplest
and most widely adopted hypermedia media types adopted when not discussing specific web stacks.

It was the first spec-based media type adopted by Spring HATEOAS.

#### 4.1.1. Building HAL representation models

As of Spring HATEOAS 1.1, we ship a dedicated `HalModelBuilder` that allows to create `RepresentationModel` instances through a HAL-idiomatic API.
These are its fundamental assumptions:

1. A HAL representation can be backed by an arbitrary object (an entity) that builds up the domain fields contained in the representation.

2. The representation can be enriched by a variety of embedded documents, which can be either arbitrary objects or HAL representations themselves (i.e. containing nested embeddeds and links).

3. Certain HAL specific patterns (e.g. previews) can be directly used in the API so that the code setting up the representation reads like you’d describe a HAL representation following those idioms.

Here’s an example of the API used:

```
// An order
var order = new Order(…); (1)

// The customer who placed the order
var customer = customer.findById(order.getCustomerId());

var customerLink = Link.of("/orders/{id}/customer") (2)
  .expand(order.getId())
  .withRel("customer");

var additional = …

var model = HalModelBuilder.halModelOf(order)
  .preview(new CustomerSummary(customer)) (3)
  .forLink(customerLink) (4)
  .embed(additional) (5)
  .link(Link.of(…, IanaLinkRelations.SELF));
  .build();
```

|**1**|                                                                                                We set up some domain type. In this case, an order that has a relationship to the customer that placed it.                                                                                                |
|-----|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|**2**|                                                                                                                We prepare a link pointing to a resource that will expose customer details                                                                                                                |
|**3**|                                                                                           We start building a preview by providing the payload that’s supposed to be rendered inside the `_embeddable` clause.                                                                                           |
|**4**|                                                     We conclude that preview by providing the target link. It transparently gets added to the `_links` object and its link relation is used as the key for the object provided in the previous step.                                                     |
|**5**|Other objects can be added to show up under `_embedded`.<br/>The key under which they’re listed is derived from the objects relation settings. They’re customizable via `@Relation` or a dedicated `LinkRelationProvider` (see [ Using the `LinkRelationProvider` API](#server.rel-provider) for details).|

```
{
  "_links" : {
    "self" : { "href" : "…" }, (1)
    "customer" : { "href" : "/orders/4711/customer" } (2)
  },
  "_embedded" : {
    "customer" : { … }, (3)
    "additional" : { … } (4)
  }
}
```

|**1**|                 The `self` link as explicitly provided.                  |
|-----|--------------------------------------------------------------------------|
|**2**|The `customer` link transparently added through `….preview(…).forLink(…)`.|
|**3**|                       The preview object provided.                       |
|**4**|           Additional elements added via explicit `….embed(…)`.           |

In HAL `_embedded` is also used to represent top collections.
They’re usually grouped under the link relation derived from the object’s type.
I.e. a list of orders would look like this in HAL:

```
{
  "_embedded" : {
    "orders : [
      … (1)
    ]
  }
}
```

|**1**|Individual order documents go here.|
|-----|-----------------------------------|

Creating such a representation is as easy as this:

```
Collection<Order> orders = …;

HalModelBuilder.emptyHalDocument()
  .embed(orders);
```

That said, if the order is empty, there’s no way to derive the link relation to appear inside `_embedded`, so that the document will stay empty if the collection is empty.

If you prefer to explicitly communicate an empty collection, a type can be handed into the overload of the `….embed(…)` method taking a `Collection`.
If the collection handed into the method is empty, this will cause a field rendered with its link relation derived from the given type.

```
HalModelBuilder.emptyHalModel()
  .embed(Collections.emptyList(), Order.class);
  // or
  .embed(Collections.emptyList(), LinkRelation.of("orders"));
```

will create the following, more explicit representation.

```
{
  "_embedded" : {
    "orders" : []
  }
}
```

#### 4.1.2. Configuring link rendering

In HAL, the `_links` entry is a JSON object. The property names are [link relations](#fundamentals.link-relations) and
each value is either [a link object or an array of link objects](https://tools.ietf.org/html/draft-kelly-json-hal-07#section-4.1.1).

For a given link relation that has two or more links, the spec is clear on representation:

Example 24. HAL document with two links associated with one relation

```
{
  "_links": {
    "item": [
      { "href": "https://myhost/cart/42" },
      { "href": "https://myhost/inventory/12" }
    ]
  },
  "customer": "Dave Matthews"
}
```

But if there is only one link for a given relation, the spec is ambiguous. You could render that as either a single object
or as a single-item array.

By default, Spring HATEOAS uses the most terse approach and renders a single-link relation like this:

Example 25. HAL document with single link rendered as an object

```
{
  "_links": {
    "item": { "href": "https://myhost/inventory/12" }
  },
  "customer": "Dave Matthews"
}
```

Some users prefer to not switch between arrays and objects when consuming HAL. They would prefer this type of rendering:

Example 26. HAL with single link rendered as an array

```
{
  "_links": {
    "item": [{ "href": "https://myhost/inventory/12" }]
  },
  "customer": "Dave Matthews"
}
```

If you wish to customize this policy, all you have to do is inject a `HalConfiguration` bean into your application configuration.
There are multiple choices.

Example 27. Global HAL single-link rendering policy

```
@Bean
public HalConfiguration globalPolicy() {
  return new HalConfiguration() //
      .withRenderSingleLinks(RenderSingleLinks.AS_ARRAY); (1)
}
```

|**1**|Override Spring HATEOAS’s default by rendering ALL single-link relations as arrays.|
|-----|-----------------------------------------------------------------------------------|

If you prefer to only override some particular link relations, you can create a `HalConfiguration`bean like this:

Example 28. Link relation-based HAL single-link rendering policy

```
@Bean
public HalConfiguration linkRelationBasedPolicy() {
  return new HalConfiguration() //
      .withRenderSingleLinksFor( //
          IanaLinkRelations.ITEM, RenderSingleLinks.AS_ARRAY) (1)
      .withRenderSingleLinksFor( //
          LinkRelation.of("prev"), RenderSingleLinks.AS_SINGLE); (2)
}
```

|**1**|           Always render `item` link relations as an array.           |
|-----|----------------------------------------------------------------------|
|**2**|Render `prev` link relations as an object when there is only one link.|

If neither of these match your needs, you can use an Ant-style path pattern:

Example 29. Pattern-based HAL single-link rendering policy

```
@Bean
public HalConfiguration patternBasedPolicy() {
  return new HalConfiguration() //
      .withRenderSingleLinksFor( //
          "http*", RenderSingleLinks.AS_ARRAY); (1)
}
```

|**1**|Render all link relations that start with `http` as an array.|
|-----|-------------------------------------------------------------|

|   |The pattern-based approach uses Spring’s `AntPathMatcher`.|
|---|----------------------------------------------------------|

All of these `HalConfiguration` withers can be combined to form one comprehensive policy. Be sure to test your API
extensively to avoid surprises.

#### 4.1.3. Link title internationalization

HAL defines a `title` attribute for its link objects.
These titles can be populated by using Spring’s resource bundle abstraction and a resource bundle named `rest-messages` so that clients can use them in their UIs directly.
This bundle will be set up automatically and is used during HAL link serialization.

To define a title for a link, use the key template `_links.$relationName.title` as follows:

Example 30. A sample `rest-messages.properties`

```
_links.cancel.title=Cancel order
_links.payment.title=Proceed to checkout
```

This will result in the following HAL representation:

Example 31. A sample HAL document with link titles defined

```
{
  "_links" : {
    "cancel" : {
      "href" : "…"
      "title" : "Cancel order"
    },
    "payment" : {
      "href" : "…"
      "title" : "Proceed to checkout"
    }
  }
}
```

####  Using the `CurieProvider` API

The [Web Linking RFC](https://tools.ietf.org/html/rfc8288#section-2.1) describes registered and extension link relation types. Registered rels are well-known strings registered with the [IANA registry of link relation types](https://www.iana.org/assignments/link-relations/link-relations.xhtml). Extension `rel` URIs can be used by applications that do not wish to register a relation type. Each one is a URI that uniquely identifies the relation type. The `rel` URI can be serialized as a compact URI or [Curie](https://www.w3.org/TR/curie). For example, a curie of `ex:persons` stands for the link relation type `[example.com/rels/persons](https://example.com/rels/persons)` if `ex` is defined as `[example.com/rels/{rel}](https://example.com/rels/{rel})`. If curies are used, the base URI must be present in the response scope.

The `rel` values created by the default `RelProvider` are extension relation types and, as a result, must be URIs, which can cause a lot of overhead. The `CurieProvider` API takes care of that: It lets you define a base URI as a URI template and a prefix that stands for that base URI. If a `CurieProvider` is present, the `RelProvider` prepends all `rel` values with the curie prefix. Furthermore a `curies` link is automatically added to the HAL resource.

The following configuration defines a default curie provider:

```
@Configuration
@EnableWebMvc
@EnableHypermediaSupport(type= {HypermediaType.HAL})
public class Config {

  @Bean
  public CurieProvider curieProvider() {
    return new DefaultCurieProvider("ex", new UriTemplate("https://www.example.com/rels/{rel}"));
  }
}
```

Note that now the `ex:` prefix automatically appears before all rel values that are not registered with IANA, as in `ex:orders`. Clients can use the `curies` link to resolve a curie to its full form.
The following example shows how to do so:

```
{
  "_links": {
    "self": {
      "href": "https://myhost/person/1"
    },
    "curies": {
      "name": "ex",
      "href": "https://example.com/rels/{rel}",
      "templated": true
    },
    "ex:orders": {
      "href": "https://myhost/person/1/orders"
    }
  },
  "firstname": "Dave",
  "lastname": "Matthews"
}
```

Since the purpose of the `CurieProvider` API is to allow for automatic curie creation, you can define only one `CurieProvider` bean per application scope.

### 4.2. HAL-FORMS

[HAL-FORMS](https://rwcbook.github.io/hal-forms/) is designed to add runtime FORM support to the [HAL media type](#mediatypes.hal).

>
>
>
>
> HAL-FORMS "looks like HAL." However, it is important to keep in mind that HAL-FORMS is not the same as HAL — the two
> should not be thought of as interchangeable in any way.
>
>
>
>

— Mike Amundsen  

> HAL-FORMS spec

To enable this media type, put the following configuration in your code:

Example 32. HAL-FORMS enabled application

```
@Configuration
@EnableHypermediaSupport(type = HypermediaType.HAL_FORMS)
public class HalFormsApplication {

}
```

Anytime a client supplies an `Accept` header with `application/prs.hal-forms+json`, you can expect something like this:

Example 33. HAL-FORMS sample document

```
{
  "firstName" : "Frodo",
  "lastName" : "Baggins",
  "role" : "ring bearer",
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/employees/1"
    }
  },
  "_templates" : {
    "default" : {
      "method" : "put",
      "contentType" : "",
      "properties" : [ {
        "name" : "firstName",
        "required" : true
      }, {
        "name" : "lastName",
        "required" : true
      }, {
        "name" : "role",
        "required" : true
      } ]
    },
    "partiallyUpdateEmployee" : {
      "method" : "patch",
      "contentType" : "",
      "properties" : [ {
        "name" : "firstName",
        "required" : false
      }, {
        "name" : "lastName",
        "required" : false
      }, {
        "name" : "role",
        "required" : false
      } ]
    }
  }
}
```

Check out the [HAL-FORMS spec](https://rwcbook.github.io/hal-forms/) to understand the details of the **\_templates** attribute.
Read about the [Affordances API](#server.affordances) to augment your controllers with this extra metadata.

As for single-item (`EntityModel`) and aggregate root collections (`CollectionModel`), Spring HATEOAS renders them
identically to [HAL documents](#mediatypes.hal).

#### 4.2.1. Defining HAL-FORMS metadata

HAL-FORMS allows to describe criterias for each form field.
Spring HATEOAS allows to customize those by shaping the model type for the input and output types and using annotations on them.

|Attribute |                                                                                                       Description                                                                                                        |
|----------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|`readOnly`|Set to `true` if there’s no setter method for the property. If that is present, use Jackson’s `@JsonProperty(Access.READ_ONLY)` on the accessors or field explicitly. Not rendered by default, thus defaulting to `false`.|
| `regex`  |  Can be customized by using JSR-303’s `@Pattern` annotation either on the field or a type. In case of the latter the pattern will be used for every property declared as that particular type. Not rendered by default.  |
|`required`|          Can be customized by using JSR-303’s `@NotNull`. Not rendered by default and thus defaulting to `false`. Templates using `PATCH` as method will automatically have all properties set to not required.          |

For types that you cannot annotate manually, you can register a custom pattern via a `HalFormsConfiguration` bean present in the application context.

```
@Configuration
class CustomConfiguration {

  @Bean
  HalFormsConfiguration halFormsConfiguration() {

    HalFormsConfiguration configuration = new HalFormsConfiguration();
    configuration.registerPatternFor(CreditCardNumber.class, "[0-9]{16}");
  }
}
```

This setup will cause the HAL-FORMS template properties for representation model properties of type `CreditCardNumber` to declare a `regex` field with value `[0-9]{16}`.

#### 4.2.2. Internationalization of form attributes

HAL-FORMS contains attributes that are intended for human interpretation, like a template’s title or property prompts.
These can be defined and internationalized using Spring’s resource bundle support and the `rest-messages` resource bundle configured by Spring HATEOAS by default.

##### Template titles

To define a template title use the following pattern: `_templates.$affordanceName.title`. Note that in HAL-FORMS, the name of a template is `default` if it is the only one.
This means that you’ll usually have to qualify the key with the local or fully qualified input type name that affordance describes.

Example 34. Defining HAL-FORMS template titles

```
_templates.default.title=Some title (1)
_templates.putEmployee.title=Create employee (2)
Employee._templates.default.title=Create employee (3)
com.acme.Employee._templates.default.title=Create employee (4)
```

|**1**|                                                                A global definition for the title using `default` as key.                                                                |
|-----|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|**2**|A global definition for the title using the actual affordance name as key. Unless defined explicitly when creating the affordance, this defaults to `$httpMethod + $simpleInputTypeName`.|
|**3**|                                                          A locally defined title to be applied to all types named `Employee`.                                                           |
|**4**|                                                                 A title definition using the fully-qualified type name.                                                                 |

|   |Keys using the actual affordance name enjoy preference over the defaulted ones.|
|---|-------------------------------------------------------------------------------|

##### Property prompts

Property prompts can also be resolved via the `rest-messages` resource bundle automatically configured by Spring HATEOAS.
The keys can be defined globally, locally or fully-qualified and need an `._prompt` concatenated to the actual property key:

Example 35. Defining prompts for an `email` property

```
firstName._prompt=Firstname (1)
Employee.firstName._prompt=Firstname (2)
com.acme.Employee.firstName._prompt=Firstname (3)
```

|**1**|All properties named `firstName` will get "Firstname" rendered, independent of the type they’re declared in.|
|-----|------------------------------------------------------------------------------------------------------------|
|**2**|              The `firstName` property in types named `Employee` will be prompted "Firstname".              |
|**3**|         The `firstName` property of `com.acme.Employee` will get a prompt of "Firstname" assigned.         |

A sample document with both template titles and property prompts defined would then look something like this:

Example 36. A sample HAL-FORMS document with internationalized template titles and property prompts

```
{
  …,
  "_templates" : {
    "default" : {
      "title" : "Create employee",
      "method" : "put",
      "contentType" : "",
      "properties" : [ {
        "name" : "firstName",
        "prompt" : "Firstname",
        "required" : true
      }, {
        "name" : "lastName",
        "prompt" : "Lastname",
        "required" : true
      }, {
        "name" : "role",
        "prompt" : "Role",
        "required" : true
      } ]
    }
  }
}
```

### 4.3. HTTP Problem Details

[Problem Details for HTTP APIs](https://tools.ietf.org/html/rfc7807) is a media type to carry machine-readable details of errors in a HTTP response to avoid the need to define new error response formats for HTTP APIs.

HTTP Problem Details defines a set of JSON properties that carry additional information to describe error details to HTTP clients.
Find more details about those properties in particular in the relevant section of the [RFC document](https://tools.ietf.org/html/rfc7807#section-3.1).

You can create such a JSON response by using the `Problem` media type domain type in your Spring MVC Controller:

Reporting problem details using Spring HATEOAS' `Problem` type

```
@RestController
class PaymentController {

  @PutMapping
  ResponseEntity<?> issuePayment(@RequestBody PaymentRequest request) {

    PaymentResult result = payments.issuePayment(request.orderId, request.amount);

    if (result.isSuccess()) {
      return ResponseEntity.ok(result);
    }

    String title = messages.getMessage("payment.out-of-credit");
    String detail = messages.getMessage("payment.out-of-credit.details", //
        new Object[] { result.getBalance(), result.getCost() });

    Problem problem = Problem.create() (1)
        .withType(OUT_OF_CREDIT_URI) //
        .withTitle(title) (2)
        .withDetail(detail) //
        .withInstance(PAYMENT_ERROR_INSTANCE.expand(result.getPaymentId())) //
        .withProperties(map -> { (3)
          map.put("balance", result.getBalance());
          map.put("accounts", Arrays.asList( //
              ACCOUNTS.expand(result.getSourceAccountId()), //
              ACCOUNTS.expand(result.getTargetAccountId()) //
          ));
        });

    return ResponseEntity.status(HttpStatus.FORBIDDEN) //
        .body(problem);
  }
}
```

|**1**|                                                 You start by creating an instance of `Problem` using the factory methods exposed.                                                 |
|-----|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|**2**|You can define the values for the default properties defined by the media type, e.g. the type URI, the title and details using internationalization features of Spring (see above).|
|**3**|                                                   Custom properties can be added via a `Map` or an explicit object (see below).                                                   |

To use a dedicated object for custom properties, declare a type, create and populate an instance of it and hand this into the `Problem` instance either via `….withProperties(…)` or on instance creation via `Problem.create(…)`.

Using a dedicated type to capture extended problem properties

```
class AccountDetails {
  int balance;
  List<URI> accounts;
}

problem.withProperties(result.getDetails());

// or

Problem.create(result.getDetails());
```

This will result in a response looking like this:

A sample HTTP Problem Details response

```
{
  "type": "https://example.com/probs/out-of-credit",
  "title": "You do not have enough credit.",
  "detail": "Your current balance is 30, but that costs 50.",
  "instance": "/account/12345/msgs/abc",
  "balance": 30,
  "accounts": ["/account/12345",
               "/account/67890"]
}
```

### 4.4. Collection+JSON

[Collection+JSON](http://amundsen.com/media-types/collection/format/) is a JSON spec registered with IANA-approved media type `application/vnd.collection+json`.

>
>
>
>
> [Collection+JSON](http://amundsen.com/media-types/collection/) is a JSON-based read/write hypermedia-type designed to support
> management and querying of simple collections.
>
>
>
>

— Mike Amundsen  

> Collection+JSON spec

Collection+JSON provides a uniform way to represent both single item resources as well as collections.
To enable this media type, put the following configuration in your code:

Example 37. Collection+JSON enabled application

```
@Configuration
@EnableHypermediaSupport(type = HypermediaType.COLLECTION_JSON)
public class CollectionJsonApplication {

}
```

This configuration will make your application respond to requests that have an `Accept` header of `application/vnd.collection+json`as shown below.

The following example from the spec shows a single item:

Example 38. Collection+JSON single item example

```
{
  "collection": {
    "version": "1.0",
    "href": "https://example.org/friends/", (1)
    "links": [   (2)
      {
        "rel": "feed",
        "href": "https://example.org/friends/rss"
      },
      {
        "rel": "queries",
        "href": "https://example.org/friends/?queries"
      },
      {
        "rel": "template",
        "href": "https://example.org/friends/?template"
      }
    ],
    "items": [  (3)
      {
        "href": "https://example.org/friends/jdoe",
        "data": [  (4)
          {
            "name": "fullname",
            "value": "J. Doe",
            "prompt": "Full Name"
          },
          {
            "name": "email",
            "value": "[email protected]",
            "prompt": "Email"
          }
        ],
        "links": [ (5)
          {
            "rel": "blog",
            "href": "https://examples.org/blogs/jdoe",
            "prompt": "Blog"
          },
          {
            "rel": "avatar",
            "href": "https://examples.org/images/jdoe",
            "prompt": "Avatar",
            "render": "image"
          }
        ]
      }
    ]
  }
}
```

|**1**|                         The `self` link is stored in the document’s `href` attribute.                         |
|-----|---------------------------------------------------------------------------------------------------------------|
|**2**|          The document’s top `links` section contains collection-level links (minus the `self` link).          |
|**3**|The `items` section contains a collection of data. Since this is a single-item document, it only has one entry.|
|**4**|                    The `data` section contains actual content. It’s made up of properties.                    |
|**5**|                                        The item’s individual `links`.                                         |

|   |The previous fragment was lifted from the spec. When Spring HATEOAS renders an `EntityModel`, it will:<br/><br/>* Put the `self` link into both the document’s `href` attribute and the item-level `href` attribute.<br/><br/>* Put the rest of the model’s links into both the top-level `links` as well as the item-level `links`.<br/><br/>* Extract the properties from the `EntityModel` and turn them into …​|
|---|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

When rendering a collection of resources, the document is almost the same, except there will be multiple entries inside
the `items` JSON array, one for each entry.

Spring HATEOAS more specifically will:

* Put the entire collection’s `self` link into the top-level `href` attribute.

* The `CollectionModel` links (minus `self`) will be put into the top-level `links`.

* Each item-level `href` will contain the corresponding `self` link for each entry from the `CollectionModel.content` collection.

* Each item-level `links` will contain all other links for each entry from `CollectionModel.content`.

### 4.5. UBER - Uniform Basis for Exchanging Representations

[UBER](https://rawgit.com/uber-hypermedia/specification/master/uber-hypermedia.html) is an experimental JSON spec

>
>
>
>
> The UBER document format is a minimal read/write hypermedia type designed to support simple state transfers and ad-hoc
> hypermedia-based transitions.
>
>
>
>

— Mike Amundsen  

> UBER spec

UBER provides a uniform way to represent both single item resources as well as collections. To enable this media type, put the following configuration in your code:

Example 39. UBER+JSON enabled application

```
@Configuration
@EnableHypermediaSupport(type = HypermediaType.UBER)
public class UberApplication {

}
```

This configuration will make your application respond to requests using the `Accept` header `application/vnd.amundsen-uber+json`as show below:

Example 40. UBER sample document

```
{
  "uber" : {
    "version" : "1.0",
    "data" : [ {
      "rel" : [ "self" ],
      "url" : "/employees/1"
    }, {
      "name" : "employee",
      "data" : [ {
        "name" : "role",
        "value" : "ring bearer"
      }, {
        "name" : "name",
        "value" : "Frodo"
      } ]
    } ]
  }
}
```

This media type is still under development as is the spec itself. Feel free to[open a ticket](https://github.com/spring-projects/spring-hateoas/issues) if you run into issues using it.

|   |**UBER media type** is not associated in any way with **Uber Technologies Inc.**, the ride sharing company.|
|---|-----------------------------------------------------------------------------------------------------------|

### 4.6. ALPS - Application-Level Profile Semantics

[ALPS](https://tools.ietf.org/html/draft-amundsen-richardson-foster-alps-01) is a media type for providing
profile-based metadata about another resource.

>
>
>
>
> An ALPS document can be used as a profile to
> explain the application semantics of a document with an application-
> agnostic media type (such as HTML, HAL, Collection+JSON, Siren,
> etc.). This increases the reusability of profile documents across
> media types.
>
>
>
>

— Mike Amundsen  

> ALPS spec

ALPS requires no special activation. Instead you "build" an `Alps` record and return it from either a Spring MVC or a Spring WebFlux web method as shown below:

Example 41. Building an `Alps` record

```
@GetMapping(value = "/profile", produces = ALPS_JSON_VALUE)
Alps profile() {

  return Alps.alps() //
      .doc(doc() //
          .href("https://example.org/samples/full/doc.html") //
          .value("value goes here") //
          .format(Format.TEXT) //
          .build()) //
      .descriptor(getExposedProperties(Employee.class).stream() //
          .map(property -> Descriptor.builder() //
              .id("class field [" + property.getName() + "]") //
              .name(property.getName()) //
              .type(Type.SEMANTIC) //
              .ext(Ext.builder() //
                  .id("ext [" + property.getName() + "]") //
                  .href("https://example.org/samples/ext/" + property.getName()) //
                  .value("value goes here") //
                  .build()) //
              .rt("rt for [" + property.getName() + "]") //
              .descriptor(Collections.singletonList(Descriptor.builder().id("embedded").build())) //
              .build()) //
          .collect(Collectors.toList()))
      .build();
}
```

* This example leverages `PropertyUtils.getExposedProperties()` to extract metadata about the domain object’s attributes.

This fragment has test data plugged in. It yields JSON like this:

Example 42. ALPS JSON

```
{
  "version": "1.0",
  "doc": {
    "format": "TEXT",
    "href": "https://example.org/samples/full/doc.html",
    "value": "value goes here"
  },
  "descriptor": [
    {
      "id": "class field [name]",
      "name": "name",
      "type": "SEMANTIC",
      "descriptor": [
        {
          "id": "embedded"
        }
      ],
      "ext": {
        "id": "ext [name]",
        "href": "https://example.org/samples/ext/name",
        "value": "value goes here"
      },
      "rt": "rt for [name]"
    },
    {
      "id": "class field [role]",
      "name": "role",
      "type": "SEMANTIC",
      "descriptor": [
        {
          "id": "embedded"
        }
      ],
      "ext": {
        "id": "ext [role]",
        "href": "https://example.org/samples/ext/role",
        "value": "value goes here"
      },
      "rt": "rt for [role]"
    }
  ]
}
```

Instead of linking each field "automatically" to a domain object’s fields, you can write them by hand if you like. It’s also possible
to use Spring Framework’s message bundles and the `MessageSource` interface. This gives you the ability to delegate these values to
locale-specific message bundles and even internationalize the metadata.

### 4.7. Community-based media types

Thanks to the [ability to create your own media type](#mediatypes.custom), there are several community-led efforts to build additional media types.

#### 4.7.1. JSON:API

* [Specification](https://jsonapi.org)

* Media type designation: `application/vnd.api+json`

* Latest Release

  * [Reference documentation](https://toedter.github.io/spring-hateoas-jsonapi/release/reference/index.html)

  * [API documentation](https://toedter.github.io/spring-hateoas-jsonapi/release/api/index.html)

* Current Snapshot

  * [Reference documentation](https://toedter.github.io/spring-hateoas-jsonapi/snapshot/reference/index.html)

  * [API documentation](https://toedter.github.io/spring-hateoas-jsonapi/snapshot/api/index.html)

* [Source](https://github.com/toedter/spring-hateoas-jsonapi)

* Project Lead: [Kai Toedter](https://github.com/toedter)

Maven coordinates

```
<dependency>
    <groupId>com.toedter</groupId>
    <artifactId>spring-hateoas-jsonapi</artifactId>
    <version>{see project page for current version}</version>
</dependency>
```

Gradle coordinates

```
implementation 'com.toedter:spring-hateoas-jsonapi:{see project page for current version}'
```

Visit the project page for more details if you want snapshot releases.

#### 4.7.2. Siren

* [Specification](https://github.com/kevinswiber/siren)

* Media type designation: `application/vnd.siren+json`

* [Reference documentation](https://spring-hateoas-siren.ingogriebsch.de)

* [javadocs](https://spring-hateoas-siren.ingogriebsch.de/apidocs)

* [Source](https://github.com/ingogriebsch/spring-hateoas-siren)

* Project Lead: [Ingo Griebsch](https://github.com/ingogriebsch)

Maven coordinates

```
<dependency>
    <groupId>de.ingogriebsch.hateoas</groupId>
    <artifactId>spring-hateoas-siren</artifactId>
    <version>{see project page for current version}</version>
    <scope>compile</scope>
</dependency>
```

Gradle coordinates

```
implementation 'de.ingogriebsch.hateoas:spring-hateoas-siren:{see project page for current version}'
```

### 4.8. Registering a custom media type

Spring HATEOAS allows you to integrate custom media types through an SPI.
The building blocks of such an implementation are:

1. Some form of Jackson `ObjectMapper` customization. In its most simple case that’s a Jackson `Module` implementation.

2. A `LinkDiscoverer` implementation so that the client-side support is able to detect links in representations.

3. A small bit of infrastructure configuration that will allow Spring HATEOAS to find the custom implementation and pick it up.

#### 4.8.1. Custom media type configuration

Custom media type implementations are picked up by Spring HATEOAS by scanning the application context for any implementations of the `HypermediaMappingInformation` interface.
Each media type must implement this interface in order to:

* Be applied to [`WebClient`](#client.web-client), [`WebTestClient`](#client.web-test-client), or [`RestTemplate`](#client.rest-template) instances.

* Support serving that media type from Spring Web MVC and Spring WebFlux controllers.

To define your own media type could look as simple as this:

```
@Configuration
public class MyMediaTypeConfiguration implements HypermediaMappingInformation {

  @Override
  public List<MediaType> getMediaTypes() {
    return MediaType.parse("application/vnd-acme-media-type") (1)
  }

  @Override
  public Module getJacksonModule() {
    return new Jackson2MyMediaTypeModule(); (2)
  }

  @Bean
  MyLinkDiscoverer myLinkDiscoverer() {
    return new MyLinkDiscoverer(); (3)
  }
}
```

|**1**|The configuration class returns the media type it supports. This applies to both server-side and client-side scenarios.|
|-----|-----------------------------------------------------------------------------------------------------------------------|
|**2**|  It overrides `getJacksonModule()` to provide custom serializers to create the media type specific representations.   |
|**3**|              It also declares a custom `LinkDiscoverer` implementation for further client-side support.               |

The Jackson module usually declares `Serializer` and `Deserializer` implementations for the representation model types `RepresentationModel`, `EntityModel`, `CollectionModel` and `PagedModel`.
In case you need further customization of the Jackson `ObjectMapper` (like a custom `HandlerInstantiator`), you can alternatively override `configureObjectMapper(…)`.

|   |Prior versions of reference documentation has mentioned implementing the `MediaTypeConfigurationProvider` interface and registering it with `spring.factories`.<br/>This is NOT necessary.<br/>This SPI is ONLY used for out-of-the-box media types provided by Spring HATEOAS.<br/>Merely implementing the `HypermediaMappingInformation` interface and registering it as a Spring bean is all that’s needed.|
|---|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

#### 4.8.2. Recommendations

The preferred way to implement media type representations is by providing a type hierarchy that matches the expected format and can be serialized by Jackson as is.
In the `Serializer` and `Deserializer` implementations registered for `RepresentationModel`, convert the instances into the media type-specific model types and then lookup the Jackson serializer for those.

The media types supported by default use the same configuration mechanism as third-party implementations would do.
So it’s worth studying the implementations in [the `mediatype` package](https://github.com/spring-projects/spring-hateoas/tree/master/src/main/java/org/springframework/hateoas/mediatype).
Note, that the built in media type implementations keep their configuration classes package private, as they’re activated via `@EnableHypermediaSupport`.
Custom implementations should probably make those public instead to make sure, users can import those configuration classes from their application packages.

## 5. Configuration

This section describes how to configure Spring HATEOAS.

### 5.1. Using `@EnableHypermediaSupport`

To let the `RepresentationModel` subtypes be rendered according to the specification of various hypermedia representation types, you can activate support for a particular hypermedia representation format through `@EnableHypermediaSupport`. The annotation takes a `HypermediaType` enumeration as its argument. Currently, we support [HAL](https://tools.ietf.org/html/draft-kelly-json-hal) as well as a default rendering. Using the annotation triggers the following:

* It registers necessary Jackson modules to render `EntityModel` and `CollectionModel` in the hypermedia specific format.

* If JSONPath is on the classpath, it automatically registers a `LinkDiscoverer` instance to look up links by their `rel` in plain JSON representations (see [Using `LinkDiscoverer` Instances](#client.link-discoverer)).

* By default, it enables [entity links](#fundamentals.obtaining-links.entity-links) and automatically picks up `EntityLinks` implementations and bundles them into a `DelegatingEntityLinks` instance that you can autowire.

* It automatically picks up all `RelProvider` implementations in the `ApplicationContext` and bundles them into a `DelegatingRelProvider` that you can autowire. It registers providers to consider `@Relation` on domain types as well as Spring MVC controllers. If the [EVO inflector](https://github.com/atteo/evo-inflector) is on the classpath, collection `rel` values are derived by using the pluralizing algorithm implemented in the library (see [[spis.rel-provider]](#spis.rel-provider)).

#### 5.1.1. Explicitly enabling support for dedicated web stacks

By default, `@EnableHypermediaSupport` will reflectively detect the web application stack you’re using and hook into the Spring components registered for those to enable support for hypermedia representations.
However, there are situations in which you’d only explicitly want to activate support for a particular stack.
E.g. if your Spring WebMVC based application uses WebFlux' `WebClient` to make outgoing requests and that one is not supposed to work with hypermedia elements, you can restrict the functionality to be enabled by explicitly declaring WebMVC in the configuration:

Example 43. Explicitly activating hypermedia support for a particular web stack

```
@EnableHypermediaSupport(…, stacks = WebStack.WEBMVC)
class MyHypermediaConfiguration { … }
```

## 6. Client-side Support

This section describes Spring HATEOAS’s support for clients.

### 6.1. Traverson

Spring HATEOAS provides an API for client-side service traversal. It is inspired by the [Traverson JavaScript library](https://blog.codecentric.de/en/2013/11/traverson/).
The following example shows how to use it:

```
Map<String, Object> parameters = new HashMap<>();
parameters.put("user", 27);

Traverson traverson = new Traverson(URI.create("http://localhost:8080/api/"), MediaTypes.HAL_JSON);
String name = traverson
    .follow("movies", "movie", "actor").withTemplateParameters(parameters)
    .toObject("$.name");
```

You can set up a `Traverson` instance by pointing it to a REST server and configuring the media types you want to set as `Accept` headers. You can then define the relation names you want to discover and follow. Relation names can either be simple names or JSONPath expressions (starting with an `$`).

The sample then hands a parameter map into the `Traverson` instance. The parameters are used to expand URIs (which are templated) found during the traversal. The traversal is concluded by accessing the representation of the final traversal. In the preceding example, we evaluate a JSONPath expression to access the actor’s name.

The preceding example is the simplest version of traversal, where the `rel` values are strings and, at each hop, the same template parameters are applied.

There are more options to customize template parameters at each level.
The following example shows these options.

```
ParameterizedTypeReference<EntityModel<Item>> resourceParameterizedTypeReference = new ParameterizedTypeReference<EntityModel<Item>>() {};

EntityModel<Item> itemResource = traverson.//
    follow(rel("items").withParameter("projection", "noImages")).//
    follow("$._embedded.items[0]._links.self.href").//
    toObject(resourceParameterizedTypeReference);
```

The static `rel(…​)` function is a convenient way to define a single `Hop`. Using `.withParameter(key, value)` makes it simple to specify URI template variables.

|   |`.withParameter()` returns a new `Hop` object that is chainable. You can string together as many `.withParameter` as you like. The result is a single `Hop` definition.<br/>The following example shows one way to do so:|
|---|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

```
ParameterizedTypeReference<EntityModel<Item>> resourceParameterizedTypeReference = new ParameterizedTypeReference<EntityModel<Item>>() {};

Map<String, Object> params = Collections.singletonMap("projection", "noImages");

EntityModel<Item> itemResource = traverson.//
    follow(rel("items").withParameters(params)).//
    follow("$._embedded.items[0]._links.self.href").//
    toObject(resourceParameterizedTypeReference);
```

You can also load an entire `Map` of parameters by using `.withParameters(Map)`.

|   |`follow()` is chainable, meaning you can string together multiple hops, as shown in the preceding examples. You can either put multiple string-based `rel` values (`follow("items", "item")`) or a single hop with specific parameters.|
|---|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

#### 6.1.1. `EntityModel<T>` vs. `CollectionModel<T>`

The examples shown so far demonstrate how to sidestep Java’s type erasure and convert a single JSON-formatted resource into a `EntityModel<Item>` object. However, what if you get a collection like an `\_embedded` HAL collection?
You can do so with only one slight tweak, as the following example shows:

```
CollectionModelType<Item> collectionModelType =
    TypeReferences.CollectionModelType<Item>() {};

CollectionModel<Item> itemResource = traverson.//
    follow(rel("items")).//
    toObject(collectionModelType);
```

Instead of fetching a single resource, this one deserializes a collection into `CollectionModel`.

### 6.2. Using `LinkDiscoverer` Instances

When working with hypermedia enabled representations, a common task is to find a link with a particular relation type in it. Spring HATEOAS provides [JSONPath](https://code.google.com/p/json-path)-based implementations of the `LinkDiscoverer` interface for either the default representation rendering or HAL out of the box. When using `@EnableHypermediaSupport`, we automatically expose an instance supporting the configured hypermedia type as a Spring bean.

Alternatively, you can set up and use an instance as follows:

```
String content = "{'_links' :  { 'foo' : { 'href' : '/foo/bar' }}}";
LinkDiscoverer discoverer = new HalLinkDiscoverer();
Link link = discoverer.findLinkWithRel("foo", content);

assertThat(link.getRel(), is("foo"));
assertThat(link.getHref(), is("/foo/bar"));
```

### 6.3. Configuring WebClient instances

If you need configure a `WebClient` to speak hypermedia, it’s easy. Get a hold of the `HypermediaWebClientConfigurer` as shown below:

Example 44. Configuring a `WebClient` yourself

```
@Bean
WebClient.Builder hypermediaWebClient(HypermediaWebClientConfigurer configurer) { (1)
 return configurer.registerHypermediaTypes(WebClient.builder()); (2)
}
```

|**1**|Inside your `@Configuration` class, get a copy of the `HypermediaWebClientConfigurer` bean Spring HATEOAS registers.|
|-----|--------------------------------------------------------------------------------------------------------------------|
|**2**|               After creating a `WebClient.Builder`, use the configurer to register hypermedia types.               |

|   |What `HypermediaWebClientConfigurer` does it register all the right encoders and decoders with a `WebClient.Builder`. To make use of it,<br/>you need to inject the builder somewhere into your application, and run the `build()` method to produce a `WebClient`.|
|---|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

If you’re using Spring Boot, there is another way: the `WebClientCustomizer`.

Example 45. Letting Spring Boot configure things

```
@Bean (4)
WebClientCustomizer hypermediaWebClientCustomizer(HypermediaWebClientConfigurer configurer) { (1)
    return webClientBuilder -> { (2)
        configurer.registerHypermediaTypes(webClientBuilder); (3)
    };
}
```

|**1**|              When creating a Spring bean, request a copy of Spring HATEOAS’s `HypermediaWebClientConfigurer` bean.               |
|-----|----------------------------------------------------------------------------------------------------------------------------------|
|**2**|                                Use a Java 8 lambda expression to define a `WebClientCustomizer`.                                 |
|**3**|                              Inside the function call, apply the `registerHypermediaTypes` method.                               |
|**4**|Return the whole thing as a Spring bean so Spring Boot can pick it up and apply it to its autoconfigured `WebClient.Builder` bean.|

At this stage, whenever you need a concrete `WebClient`, simply inject `WebClient.Builder` into your code, and use `build()`. The `WebClient` instance
will be able to interact using hypermedia.

### 6.4. Configuring `WebTestClient` Instances

When working with hypermedia-enabled representations, a common task is to run various tests by using `WebTestClient`.

To configure an instance of `WebTestClient` in a test case, check out this example:

Example 46. Configuring `WebTestClient` when using Spring HATEOAS

```
@Test // #1225
void webTestClientShouldSupportHypermediaDeserialization() {

  // Configure an application context programmatically.
  AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
  context.register(HalConfig.class); (1)
  context.refresh();

  // Create an instance of a controller for testing
  WebFluxEmployeeController controller = context.getBean(WebFluxEmployeeController.class);
  controller.reset();

  // Extract the WebTestClientConfigurer from the app context.
  HypermediaWebTestClientConfigurer configurer = context.getBean(HypermediaWebTestClientConfigurer.class);

  // Create a WebTestClient by binding to the controller and applying the hypermedia configurer.
  WebTestClient client = WebTestClient.bindToApplicationContext(context).build().mutateWith(configurer); (2)

  // Exercise the controller.
  client.get().uri("http://localhost/employees").accept(HAL_JSON) //
      .exchange() //
      .expectStatus().isOk() //
      .expectBody(new TypeReferences.CollectionModelType<EntityModel<Employee>>() {}) (3)
      .consumeWith(result -> {
        CollectionModel<EntityModel<Employee>> model = result.getResponseBody(); (4)

        // Assert against the hypermedia model.
        assertThat(model.getRequiredLink(IanaLinkRelations.SELF)).isEqualTo(Link.of("http://localhost/employees"));
        assertThat(model.getContent()).hasSize(2);
      });
}
```

|**1**|                  Register your configuration class that uses `@EnableHypermediaSupport` to enable HAL support.                   |
|-----|----------------------------------------------------------------------------------------------------------------------------------|
|**2**|                               Use `HypermediaWebTestClientConfigurer` to apply hypermedia support.                               |
|**3**|Ask for a response of `CollectionModel<EntityModel<Employee>>` using Spring HATEOAS’s `TypeReferences.CollectionModelType` helper.|
|**4**|                              After getting the "body" in Spring HATEOAS format, assert against it!                               |

|   |`WebTestClient` is an immutable value type, so you can’t alter it in place. `HypermediaWebClientConfigurer` returns a mutated<br/>variant that you must then capture to use it.|
|---|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

If you are using Spring Boot, there are additional options, like this:

Example 47. Configuring `WebTestClient` when using Spring Boot

```
@SpringBootTest
@AutoConfigureWebTestClient (1)
class WebClientBasedTests {

    @Test
    void exampleTest(@Autowired WebTestClient.Builder builder, @Autowired HypermediaWebTestClientConfigurer configurer) { (2)
        client = builder.apply(configurer).build(); (3)

        client.get().uri("/") //
                .exchange() //
                .expectBody(new TypeReferences.EntityModelType<Employee>() {}) (4)
                .consumeWith(result -> {
                    // assert against this EntityModel<Employee>!
                });
    }
}
```

|**1**|     This is Spring Boot’s test annotation that will configure a `WebTestClient.Builder` for this test class.      |
|-----|-------------------------------------------------------------------------------------------------------------------|
|**2**|Autowire Spring Boot’s `WebTestClient.Builder` into `builder` and Spring HATEOAS’s configurer as method parameters.|
|**3**|                    Use `HypermediaWebTestClientConfigurer` to register support for hypermedia.                    |
|**4**|                    Signal you want an `EntityModel<Employee>` returned using `TypeReferences`.                    |

Again, you can use similar assertions as the earlier example.

There are many other ways to fashion test cases. `WebTestClient` can be bound to controllers, functions, and URLs. This section isn’t meant to show all that. Instead, this gives you some examples to get started. The important thing is that by applying `HypermediaWebTestClientConfigurer`, any instance of `WebTestClient` can be altered to handle hypermedia.

### 6.5. Configuring RestTemplate instances

If you want to create your own copy of `RestTemplate`, configured to speak hypermedia, you can use the `HypermediaRestTemplateConfigurer`:

Example 48. Configuring `RestTemplate` yourself

```
/**
 * Use the {@link HypermediaRestTemplateConfigurer} to configure a {@link RestTemplate}.
 */
@Bean
RestTemplate hypermediaRestTemplate(HypermediaRestTemplateConfigurer configurer) { (1)
	return configurer.registerHypermediaTypes(new RestTemplate()); (2)
}
```

|**1**|Inside your `@Configuration` class, get a copy of the `HypermediaRestTemplateConfigurer` bean Spring HATEOAS registers.|
|-----|-----------------------------------------------------------------------------------------------------------------------|
|**2**|                    After creating a `RestTemplate`, use the configurer to apply hypermedia types.                     |

You are free to apply this pattern to any instance of `RestTemplate` that you need, whether is to create a registered bean, or inside a service you define.

If you’re using Spring Boot, there is another approach.

In general, Spring Boot has moved away from the concept of registering a `RestTemplate` bean in the application context.

* When talking to different services, you often need different credentials.

* When `RestTemplate` uses an underlying connection pool, you run into additional issues.

* Users often need different instances rather than a single bean.

To compensate for this, Spring Boot provides a `RestTemplateBuilder`. This autoconfigured bean lets you define various beans used to fashion
a `RestTemplate` instance. You ask for a `RestTemplateBuilder` bean, call its `build()` method, and then apply final settings (such as credentials and other details).

To register hypermedia-based message converters, add the following to your code:

Example 49. Letting Spring Boot configure things

```
@Bean (4)
RestTemplateCustomizer hypermediaRestTemplateCustomizer(HypermediaRestTemplateConfigurer configurer) { (1)
    return restTemplate -> { (2)
        configurer.registerHypermediaTypes(restTemplate); (3)
    };
}
```

|**1**|           When creating a Spring bean, request a copy of Spring HATEOAS’s `HypermediaRestTemplateConfigurer` bean.            |
|-----|-------------------------------------------------------------------------------------------------------------------------------|
|**2**|                             Use a Java 8 lambda expression to define a `RestTemplateCustomizer`.                              |
|**3**|                             Inside the function call, apply the `registerHypermediaTypes` method.                             |
|**4**|Return the whole thing as a Spring bean so Spring Boot can pick it up and apply it to its autoconfigured `RestTemplateBuilder`.|

At this stage, whenever you need a concrete `RestTemplate`, simply inject `RestTemplateBuilder` into your code, and use `build()`. The `RestTemplate` instance
will be able to interact using hypermedia.