json-view icon indicating copy to clipboard operation
json-view copied to clipboard

Exceptions at usage

Open stanglt opened this issue 9 years ago • 3 comments

Hi,

sorry for the issue, but i saw no way to contact you directly.

i have a controller-method, that returns a single user of the system. I have tried to hide the company of the user if the caller is no superadmin.

JsonView.with(user).onClass(User.class, match().exclude("company"))

I registered your JsonView to my CustomObjectMapper as well, but the code above throws recursively exceptions.

In the README you are always using lists. Is your library not possible on single objects?

Second question: How do you return a ResponseBody with a void function? Is this the problem in my case? I return the user after i tried to filter the company attribute.

Thanks, Tobias

stanglt avatar Feb 01 '16 09:02 stanglt

It's fine to make an issue to ask questions! Can you add an example test case? I'm not really sure what's going on in your environment, that should work just fine.

monitorjbl avatar Feb 01 '16 22:02 monitorjbl

Thanks for your fast response!

I have an UserController which basically returns a user. According to the role of the calling user, several properties should not be returned to the client.

I followed your README file instructions for Spring Integration (added dependency and Bean).

@RequestMapping(value = "/{userId}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(HttpStatus.OK)
public @Valid @ResponseBody ResultWrapper<UserDataDTO> getUser(@PathVariable("userId") final String userId,
        @AuthenticationPrincipal final UserAuthentication userDetails)
    UserDataDTO initiator = userService.getOwnUserByEmail(userDetails.getName());

    UserDataDTO userDataDTO = UserService.tryGetUserDataByUserId(initiator, UUID.fromString(userId));

    ResultWrapper<UserDataDTO> wrapper = null;
    if (initiator.getRole() != Role.SuperAdmin) {
        wrapper = json.use(JsonView.with(userDataDTO).onClass(UserDataDTO.class, Match.match().exclude("company")));
    } else {
        wrapper = json.use(JsonView.with(userDataDTO));
    }

    return wrapper;
}

But if i execute the code i only get Stackoverflow here:

at com.monitorjbl.json.JsonViewSerializer$JsonWriter.write(JsonViewSerializer.java:347) ~[json-view-0.10.jar:na] at com.monitorjbl.json.JsonViewSerializer$JsonWriter.writeList(JsonViewSerializer.java:154) ~[json-view-0.10.jar:na]

I get many log entries like that. Seems like this happens in a recursion (see exception.txt) .

stanglt avatar Feb 02 '16 15:02 stanglt

You should return your object, not the ResultWrapper. You can do this:

@RequestMapping(value = "/{userId}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(HttpStatus.OK)
public @Valid @ResponseBody UserDataDTO getUser(@PathVariable("userId") final String userId,
        @AuthenticationPrincipal final UserAuthentication userDetails){
    UserDataDTO initiator = userService.getOwnUserByEmail(userDetails.getName());

    UserDataDTO userDataDTO = UserService.tryGetUserDataByUserId(initiator, UUID.fromString(userId));

    if (initiator.getRole() != Role.SuperAdmin) {
        return json.use(JsonView.with(userDataDTO).onClass(UserDataDTO.class, Match.match().exclude("company"))).returnValue();
    } else {
        return json.use(JsonView.with(userDataDTO)).returnValue();
    }
}

The returnValue() method simply returns the object so you can easily use this library if your methods have return types. Alternatively, you can not return anything. The Spring integration doesn't actually use the return value directly, so it's not required:

@RequestMapping(value = "/{userId}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(HttpStatus.OK)
public @Valid @ResponseBody void getUser(@PathVariable("userId") final String userId,
        @AuthenticationPrincipal final UserAuthentication userDetails){
    UserDataDTO initiator = userService.getOwnUserByEmail(userDetails.getName());
    UserDataDTO userDataDTO = UserService.tryGetUserDataByUserId(initiator, UUID.fromString(userId));

    if (initiator.getRole() != Role.SuperAdmin) {
        json.use(JsonView.with(userDataDTO).onClass(UserDataDTO.class, Match.match().exclude("company")));
    } else {
        json.use(JsonView.with(userDataDTO));
    }
}

monitorjbl avatar Feb 05 '16 19:02 monitorjbl