La salida de mis entidades en un servicio Sprint Boot REST HATEOAS no funciona. El servicio devuelve una cadena vacía para cada entidad. No hay mensajes de error. Probé Spring Boot 1.5.4 y 2.0.0.RC1.

El código fuente completo está en GitHub: https://github.com/murygin/hateoas-people-service

Aplicación

@SpringBootApplication
@Configuration
@EnableHypermediaSupport(type={EnableHypermediaSupport.HypermediaType.HAL})
public class Application {   
  public static void main(String args[]) {
    SpringApplication.run(Application.class);
  }
}

PersonController

@RestController
@RequestMapping(value = "/persons", produces = "application/hal+json")
public class PersonController {

  @GetMapping
  public ResponseEntity<Resources<PersonResource>> all() {
    final List<PersonResource> collection =
        getPersonList().stream().map(PersonResource::new).collect(Collectors.toList());
    final Resources<PersonResource> resources = new Resources<>(collection);
    final String uriString = ServletUriComponentsBuilder.fromCurrentRequest().build().toUriString();
    resources.add(new Link(uriString, "self"));
    return ResponseEntity.ok(resources);
  }

  @GetMapping("/{id}")
  public ResponseEntity<PersonResource> get(@PathVariable final long id) {
    Person p = new Person((long)1,"Donald","Duck");
    return ResponseEntity.ok(new PersonResource(p));
  }

  private List<Person> getPersonList() {
    List<Person> personList = new LinkedList<>();
    personList.add(new Person((long)1,"Donald","Duck"));
    personList.add(new Person((long)2,"Dagobert","Duck"));
    personList.add(new Person((long)3,"Daniel","Duesentrieb"));
    return personList;
  }

}

PersonResource

public class PersonResource extends ResourceSupport {

  private final Person person;

  public PersonResource(final Person person) {
    this.person = person;
    final long id = person.getId();
    add(linkTo(PersonController.class).withRel("people"));
    add(linkTo(methodOn(PersonController.class).get(id)).withSelfRel());
  }
}

Persona

public class Person {    
  private Long id;   
  private String firstName;   
  private String secondName;

  public Person() {
  }

  public Person(Long id, String firstName, String secondName) {
    this.id = id;
    this.firstName = firstName;
    this.secondName = secondName;
  }

  // getter and setter...
}

Salida de http: // localhost: 8080 / persons

    {
        _embedded: {
            personResourceList: [{
                    _links: {
                        people: {
                            href: "http://localhost:8080/persons"
                        },
                        self: {
                            href: "http://localhost:8080/persons/1"
                        }
                    }
                },
                {
                    _links: {
                        people: {
                            href: "http://localhost:8080/persons"
                        },
                        self: {
                            href: "http://localhost:8080/persons/2"
                        }
                    }
                },
                {
                    _links: {
                        people: {
                            href: "http://localhost:8080/persons"
                        },
                        self: {
                            href: "http://localhost:8080/persons/3"
                        }
                    }
                }
            ]
        },
        _links: {
            self: {
                href: "http://localhost:8080/persons"
            }
        }
    }

Salida de http: // localhost: 8080 / persons / 1

    {
        _links: {
            people: {
                href: "http://localhost:8080/persons"
            },
            self: {
                href: "http://localhost:8080/persons/1"
            }
        }
    }
0
uı6ʎɹnɯ ꞁəıuɐp 19 feb. 2018 a las 13:16

2 respuestas

La mejor respuesta

Agregue un captador para persona en PersonResource:

public class PersonResource extends ResourceSupport {

  private final Person person;

  public PersonResource(final Person person) {
    this.person = person;
    final long id = person.getId();
    add(linkTo(PersonController.class).withRel("people"));
    add(linkTo(methodOn(PersonController.class).get(id)).withSelfRel());
  }

    public Person getPerson() {
        return person;
    }
}

Con el captador, Spring obtiene a la persona envuelta en su PersonResource y la serializa:

OBTENGA http: // localhost: 8080 / persons / 1

{
  "person" : {
    "id" : 1,
    "firstName" : "Donald",
    "secondName" : "Duck"
  },
  "_links" : {
    "people" : {
      "href" : "http://localhost:8080/persons"
    },
    "self" : {
      "href" : "http://localhost:8080/persons/1"
    }
  }
}

OBTENGA http: // localhost: 8080 / persons

{
  "_embedded" : {
    "personResources" : [ {
      "person" : {
        "id" : 1,
        "firstName" : "Donald",
        "secondName" : "Duck"
      },
      "_links" : {
        "people" : {
          "href" : "http://localhost:8080/persons"
        },
        "self" : {
          "href" : "http://localhost:8080/persons/1"
        }
      }
    }, {
      "person" : {
        "id" : 2,
        "firstName" : "Dagobert",
        "secondName" : "Duck"
      },
      "_links" : {
        "people" : {
          "href" : "http://localhost:8080/persons"
        },
        "self" : {
          "href" : "http://localhost:8080/persons/2"
        }
      }
    }, {
      "person" : {
        "id" : 3,
        "firstName" : "Daniel",
        "secondName" : "Duesentrieb"
      },
      "_links" : {
        "people" : {
          "href" : "http://localhost:8080/persons"
        },
        "self" : {
          "href" : "http://localhost:8080/persons/3"
        }
      }
    } ]
  },
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/persons"
    }
  }
}

Nota: Soy un vago perezoso, agregué spring-boot-starter-data-rest a las dependencias pom.xml para imprimir bastante el resultado, por lo que su resultado real puede variar un poco.

1
Marc Tarin 19 feb. 2018 a las 11:31

Le sugiero un enfoque bastante menos invasivo para su caso con el uso de Resource en lugar de la extensión de ResourceSupport . Su código se vería así:

@RestController
@RequestMapping(value = "/persons", produces = "application/hal+json")
public class PersonController {

  @GetMapping
  public ResponseEntity<List<Resource<Person>>> all() {
    final List<Resource<Person>> collection =
        getPersonList().stream()
                .map(p -> new Resource<>(p, this.getLinks(p.getId())))
                .collect(Collectors.toList());
    return ResponseEntity.ok(collection);
  }

  @GetMapping("/{id}")
  public ResponseEntity<Resource<Person>> get(@PathVariable final long id) {
    Person p = new Person(id,"Donald","Duck");
    Resource<Person> resource = new Resource<>(p, this.getLinks(id));
    return ResponseEntity.ok(resource);
  }

  private List<Person> getPersonList() {
    List<Person> personList = new LinkedList<>();
    personList.add(new Person((long)1,"Donald","Duck"));
    personList.add(new Person((long)2,"Dagobert","Duck"));
    personList.add(new Person((long)3,"Daniel","Duesentrieb"));
    return personList;
  }

  private List<Link> getLinks(long id) {
      return Arrays.asList(
              linkTo(PersonController.class).withRel("people"),
              linkTo(methodOn(getClass()).get(id)).withSelfRel());
  }
}

Con salidas más claras:

OBTENGA http: // localhost: 8080 / persons / 1

{
   "id": 1,
   "firstName": "Donald",
   "secondName": "Duck",
   "_links":    {
      "people": {"href": "http://localhost:8080/persons"},
      "self": {"href": "http://localhost:8080/persons/1"}
   }
}

OBTENGA http: // localhost: 8080 / persons

[
   {
      "id": 1,
      "firstName": "Donald",
      "secondName": "Duck",
      "_links":       {
         "people": {"href": "http://localhost:8080/persons"},
         "self": {"href": "http://localhost:8080/persons/1"}
      }
   },
   {
      "id": 2,
      "firstName": "Dagobert",
      "secondName": "Duck",
      "_links":       {
         "people": {"href": "http://localhost:8080/persons"},
         "self": {"href": "http://localhost:8080/persons/2"}
      }
   },
   {
      "id": 3,
      "firstName": "Daniel",
      "secondName": "Duesentrieb",
      "_links":       {
         "people": {"href": "http://localhost:8080/persons"},
         "self": {"href": "http://localhost:8080/persons/3"}
      }
   }
]

Solo otro punto de vista, espero que esto ayude.

1
evdelacruz 20 feb. 2018 a las 16:00