Yannic Bürgmann
Yannic Bürgmann

Reputation: 6581

Spring Data Rest: RepositoryRestController deserialization from URI not working

My Problem is the deserialization of entities from URI-String. When I use the by Spring Data Rest generated HTTP interface everything works fine. I can post the following JSON against my endpoint /api/shoppingLists and it will be deserialized to a shopping list with admin as an owner.

{
  "name":"Test", 
  "owners":["http://localhost:8080/api/sLUsers/admin"]

}

When I use a custom RepositoryRestController this doesn't work anymore. If I post exactly the same JSON to the same endpoint I get this response.

{
  "timestamp" : "2015-11-15T13:18:34.550+0000",
  "status" : 400,
  "error" : "Bad Request",
  "exception" : "org.springframework.http.converter.HttpMessageNotReadableException",
  "message" : "Could not read document: Can not instantiate value of type [simple type, class de.yannicklem.shoppinglist.core.user.entity.SLUser] from String value ('http://localhost:8080/api/sLUsers/admin'); no single-String constructor/factory method\n at [Source: java.io.PushbackInputStream@9cad4d2; line: 1, column: 26] (through reference chain: de.yannicklem.shoppinglist.core.list.entity.ShoppingList[\"owners\"]->java.util.HashSet[0]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not instantiate value of type [simple type, class de.yannicklem.shoppinglist.core.user.entity.SLUser] from String value ('http://localhost:8080/api/sLUsers/admin'); no single-String constructor/factory method\n at [Source: java.io.PushbackInputStream@9cad4d2; line: 1, column: 26] (through reference chain: de.yannicklem.shoppinglist.core.list.entity.ShoppingList[\"owners\"]->java.util.HashSet[0])",
  "path" : "/api/shoppingLists"
}

My RepositoryRestController:

@RepositoryRestController
@ExposesResourceFor(ShoppingList.class)
@RequiredArgsConstructor(onConstructor = @__(@Autowired ))
public class ShoppingListRepositoryRestController {

  private final ShoppingListService shoppingListService;

  private final CurrentUserService currentUserService;

  @RequestMapping(method = RequestMethod.POST, value = ShoppingListEndpoints.SHOPPING_LISTS_ENDPOINT)
  @ResponseBody
  @ResponseStatus(HttpStatus.CREATED)
  public PersistentEntityResource postShoppingList(@RequestBody ShoppingList shoppingList,
    PersistentEntityResourceAssembler resourceAssembler) {

    if (shoppingListService.exists(shoppingList)) {
        shoppingListService.handleBeforeSave(shoppingList);
    } else {
        shoppingListService.handleBeforeCreate(shoppingList);
    }

    return resourceAssembler.toResource(shoppingListService.save(shoppingList));
  }
}

Could anybody tell me why the deserialization doesn't work anymore with a custom RepositoryRestController (which is suggested by the docs)?

To take advantage of Spring Data REST’s settings, message converters, exception handling, and more, use the @RepositoryRestController annotation instead of a standard Spring MVC @Controller or @RestController

For the full source code please have a look at the GitHub repo

Upvotes: 7

Views: 1989

Answers (2)

algarcon
algarcon

Reputation: 13

In my case the problem was a difference between the field name at the pojo and the json field. i.e:

@Entity
public class Pojo{

   @ManyToOne(fetch = FetchType.EAGER, cascade = { CascadeType.ALL })
   @JoinColumn(name = "fk_myother")
   public Other myOther;
...etc
}

POST -> /dao/pojos
{
   "myother":"http://localhost:8034/dao/others/50"
}

pay attention that the json field should be "myOther" instead.

Hope this helps to someone.

Upvotes: 0

Alex
Alex

Reputation: 11

In order to use the HAL MessageConverter you should have a Resource as a paramter. Try changing your code to:

 public PersistentEntityResource postShoppingList(@RequestBody Resource<ShoppingList> shoppingList)

Upvotes: 1

Related Questions