简体   繁体   中英

Why does Spring Data Rest mangle / corrupt data when binding to entity?

On the client and server side, I have:

@Data
public class Car {
  private Long id;
}

@Data
public class GroupMember {
    private Long id;
    private Group group; // has only single field, id
    private Car car;
    private Car groupCar;
}

Note: On the server side these are entities. (I'm using Spring Boot Data Rest to save.)

The client creates a car and then tries to create a group member for that car as follows:

Car car = new Car();
car = client.save(car); // this works fine

GroupMember gm = new GroupMember();
gm.setGroup(new Group(1L));
gm.setGroupCar(car);
gm.setCar(car);
client.save(gm); // this fails

client is a instance of CarClient :

@FeignClient(name = "car")
public interface CarClient {
    
    @PostMapping("/api/cars")
    public Car save(Car car);
    
    @PostMapping("/api/groupMembers")
    public GroupMember save(GroupMember groupMember);
    
}

client.save(GroupMember) fails with

[409] during [POST] to [http://car/api/groupMembers] [CarClient#save(GroupMember)]: [{"cause":{"cause":{"cause":null,"message":"Cannot insert the value NULL into column 'groupCarId', table 'cars.dbo.GroupMember'; column does not allow nulls. INSERT fails."}

After turning on trace on the server side, I can see that groupCar (and car ) is null:

2022-06-30 16:25:47.333 TRACE 16840 --- [http-nio-9009-exec-1] .w.s.m.m.a.ServletInvocableHandlerMethod : Arguments: [org.springframework.data.rest.webmvc.RootResourceInformation@5ca2b05f, Resource { content: GroupMember(id=10640, group=Group(id=1), car=null, groupCar=null), links: [] }, org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler@47f7b8a2, */*]

Also, the GroupMember id was set to the car id, 10640

Why did Spring Data Rest incorrectly bind the properties of GroupMember?

Update

Because Spring Data Rest appears to be broken in its binding, I created a controller as follows:

@RestController
@RequiredArgsConstructor
@RequestMapping("/groupMember")
@Slf4j
public class GroupMemberController {

    private final GroupMemberRepository repo;
    
    @PostMapping
    public GroupMember save(@RequestBody GroupMember groupMember) {
        log.info("GROUP MEMBER is {}", groupMember);
        return repo.save(groupMember);

    }
} 

and then revised my FeignClient to point to that for saving a GroupMember:

@FeignClient(name = "car")
public interface CarClient {
    
    @PostMapping("/api/cars")
    public Car save(Car car);
    
    @PostMapping("/groupMember")
    public GroupMember save(GroupMember groupMember);
    
}

This works as expected. I can see from the log that:

2022-07-01 13:02:04.637  INFO 764 --- [nio-9009-exec-1] com.example.GroupMemberController    : GROUP MEMBER is GroupMember(id=null, group=Group(id=1), car=car(id=10653), groupCar=Security(id=10653))

Am I doing something wrong with Spring Data Rest or can it not handle POSTing this type of data?

Spring Data Rest tries to deserialize the Car fields in GroupMember using URIs. There are no URIs provided by the client though. Instead, groupCar and car are nested objects in the JSON.

Adding @RestResource(exported = false) on the two car fields within GroupMember (on the server side) resolves the issue by telling Spring Data Rest to expect nested objects instead of URIs.

Alternatively, an EntityModel<GroupMember> could be passed from the client.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM