Feign and HAL/resources

半腔热情 提交于 2019-12-04 11:17:50

I found the problem. The Exception occured due to the fact that the response from the REST API was a single response. So it failed to see it as a List of entities.

When I added (building on the code above):

mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);

It works

Edit: On a side note, I had implemented the FeignClient like this:

@Service
@FeignClient(UsersConstants.USER_SERVICE_NAME)
public interface UsersServices {

    @RequestMapping(method = RequestMethod.GET, value = "/user")
    List<User> getUsers();
}

But how it should be, since it's a pageable resource:

@Service
@FeignClient(UsersConstants.USER_SERVICE_NAME)
public interface UsersServices {

    @RequestMapping(method = RequestMethod.GET, value = "/user")
    List<PagedResources<User>> getUsers();
}

The PagedResource is found within HATEOAS dependency:

<dependency>
    <groupId>org.springframework.hateoas</groupId>
    <artifactId>spring-hateoas</artifactId>
</dependency>

It also has a lot of other classes that can help out, such as Resource, Resources and so forth.

This worked for me:

@EnableHypermediaSupport(type = EnableHypermediaSupport.HypermediaType.HAL)
@SpringBootApplication
@EnableFeignClients
public class Application {
....
}

Note the @EnableHypermediaSupport

@FeignClient(url = "http://localhost:8080")
public interface PersonClient {
    @RequestMapping(method = RequestMethod.GET, value = "/persons")
    Resources<Person> getPersons();

    @RequestMapping(method = RequestMethod.GET, value = "/persons/{id}")
    Resource<Person> getPerson(@PathVariable("id") long id);
}

I have created a fully working example here: https://github.com/jtdev/spring-feign-data-rest-example

Note that simply switchen the maven pom from spring-boot to spring-cloud (without changing code), may easily result in json errors.

You should define a feignDecoder bean in your application. If you have spring-hateoas in your environment then try something like this:

@Bean
public Decoder feignDecoder() {
    ObjectMapper mapper = new ObjectMapper()
            .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
            .registerModule(new Jackson2HalModule());

    return new ResponseEntityDecoder(new JacksonDecoder(mapper));
}

Then you can consume your HAL as PagedResource.

I got this to work for me (Thanks @Devabc, you're example helped me a lot):

I wanted to get PagedResources of a Resource for a User.

Remember to add @EnableHypermediaSupport(type = EnableHypermediaSupport.HypermediaType.HAL) to your main application class.

My Feign client looks as follows:

@FeignClient("user-microservice")
public interface UserClient {
  @RequestMapping(method = RequestMethod.GET, value = "/user")
  PagedResources<Resource<User>> findAll();
}

Also remember to add a default and parameterised constructor for your model. (in my case User) I'm not sure why but this seemed to fix my serialisation issue that I had.

Lastly I Used this version of Feign

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-feign</artifactId>
  <version>1.1.5.RELEASE</version>
</dependency>

check the link

The comment below from Greg Turnquist did work for collection type return

C) the type to extract from the collection should be Resources<Resource<Question>>. The collection has links as does each each entry of the collection.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!