My controller can't seem to find the HATEOAS methods like "linkTo".
Am I missing something?
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework</groupId>
<artifactId>provider</artifactId>
<version>0.1.0</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.1.5.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Security -->
<!-- Auto configured, remove dependencies to disable. -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
</dependency>
<!-- OAuth 2.0 -->
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>2.0.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test-mvc</artifactId>
<version>1.0.0.M2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<!-- Spring MongoDB -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
</dependency>
<!-- Spring REST MVC -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-rest-webmvc</artifactId>
</dependency>
<!-- Dozer: DTO/Entity Mapper -->
<dependency>
<groupId>net.sf.dozer</groupId>
<artifactId>dozer</artifactId>
<version>5.3.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
</dependency>
</dependencies>
<properties>
<start-class>com.provider.core.Application</start-class>
</properties>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-snapshots</id>
<url>http://repo.spring.io/libs-snapshot</url>
<snapshots><enabled>true</enabled></snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<url>http://repo.spring.io/libs-snapshot</url>
<snapshots><enabled>true</enabled></snapshots>
</pluginRepository>
</pluginRepositories>
</project>
Controller
package com.provider.core;
import org.dozer.DozerBeanMapper;
import org.dozer.Mapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.provider.account.Account;
import com.provider.account.AccountDTO;
@Controller
public class AccountController
{
private static final Logger logger = LoggerFactory.getLogger(AccountController.class);
@Autowired private AccountRepository repo;
@RequestMapping(value = "account", method = RequestMethod.POST)
public @ResponseBody HttpEntity<AccountDTO> createAccount(@RequestBody AccountDTO accountDto) {
logger.info("Start createAccount()");
Mapper mapper = new DozerBeanMapper();
Account account = mapper.map(accountDto, Account.class);
Account savedAccount = repo.save(account);
AccountDTO savedAccountDto = mapper.map(savedAccount, AccountDTO.class);
// DOES NOT COMPILE "linkto" not defined.
savedAccountDto.add(linkTo(AccountController.class).slash(savedAccountDto.getId()).withSelfRel());
return new ResponseEntity<AccountDTO>(savedAccountDto, HttpStatus.OK);
}
}
The Spring HATEOAS project is a library of APIs that we can use to easily create REST representations that follow the principle of HATEOAS (Hypertext as the Engine of Application State).
In case you are using HATEOAS v1.0 and above (Spring boot >= 2.2.0), do note that the classnames have changed. Notably the below classes have been renamed:
ResourceSupport
changed to RepresentationModel
Resource
changed to EntityModel
Resources
changed to CollectionModel
PagedResources
changed to PagedModel
ResourceAssembler
changed to RepresentationModelAssembler
More information available in the official documentation here.
When using Spring boot starter, the below dependency would suffice to include HATEOAS:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-hateoas</artifactId>
</dependency>
Hoping this information will help someone like me who searched for hours to find why Resource
class was not getting resolved.
Looks like your POM is missing the spring-hateoas
dependency.
So first add this to pom.xml:
<dependency>
<groupId>org.springframework.hateoas</groupId>
<artifactId>spring-hateoas</artifactId>
<version>0.15.0.RELEASE</version>
</dependency>
Then you can add this static import and your code should compile:
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.*
If you are using HATEOAS in eclipse(Version : Oxygen.3a Release (4.7.3a)), please note that the class names have changed.
Resource changed to EntityModel
Resources changed to CollectionModel
More information available in the official documentation below link ->
https://docs.spring.io/spring-hateoas/docs/current/reference/html/
When using Spring boot starter, you've to use below dependency to include HATEOAS:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-hateoas</artifactId>
</dependency>
Demo Code :
EntityModel<Users> resource = new EntityModel<Users>(user);
ControllerLinkBuilder linkTo = linkTo(methodOn(this.getClass()).retrieveAllUsers());
resource.add(linkTo.withRel("all-users"));
Note : You have to import
import static org.springframework.hateoas.server.mvc.ControllerLinkBuilder.*;
Hope this information is helpful to find why Resource
class was not getting resolved !!
Add following dependency :-
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-hateoas</artifactId>
<version>2.4.0</version>
</dependency>
Follow Sample Code :-
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.*;
@GetMapping(path = "/users/{id}")
public EntityModel<User> getUserInfo(@PathVariable int id) {
User user = userDao.getUser(id);
EntityModel<User> entityModel = EntityModel.of(user);
Link link = WebMvcLinkBuilder.linkTo(methodOn(this.getClass()).getUserList()).withRel("user-list");
entityModel.add(link);
if(user == null) {
throw new UserNotFoundException("User not found with id : "+id);
}
return entityModel;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With