darrachequesne / spring-data-jpa-datatables

Spring Data JPA extension to work with the great jQuery plugin DataTables (https://datatables.net/)
Apache License 2.0
441 stars 174 forks source link

Retrieving data as JSON does not acccount for @JsonView annotation #79

Closed RomanKurbanov closed 4 years ago

RomanKurbanov commented 6 years ago

Absence of @JsonView(DataTablesOutput.View.class) does not hide the property. - That's pretty much the issue. Putting it back and removing it again does not affect visibility of any property - i tried.

RomanKurbanov commented 6 years ago

Okay, i narrowed it down a bit: if we have a DataTable sending DataTableInput through POST-reqeust - DataTablesRepository outputs fields seemingly at random. But if it uses GET-request - JsonView annotation works all of the sudden.

Tested it on a second project - same behaviour. Changed issue name.

sebasira commented 5 years ago

I'm having the same issue as you (earlier) do. I can not hide properties with @JsonView not even with @JsonIgnore. I'm using v4.3

sebasira commented 5 years ago

Well... it's strange.... now it's working with both GET and POST. I've switch back and forth from one method to another and they started to work (using @JsonView).

RomanKurbanov commented 5 years ago

@sebasira In my case it very consistently doesn't work.

sebasira commented 5 years ago

@iSosnitsky give a few days and I'll put my code here

RomanKurbanov commented 5 years ago

Now things get kinda odd. It totally works if i use findAll(); with an empty DataTablesInput, like that:

@JsonView(DataTablesOutput.View.class)
    @RequestMapping(value = "/users", method = RequestMethod.GET)
    public DataTablesOutput<User> getUsers() {
        return userRepository.findAll(new DataTablesInput());
    }

But if i use DataTables provided input, it stops working:

@JsonView(DataTablesOutput.View.class)
    @RequestMapping(value = "/users", method = RequestMethod.GET)
    public DataTablesOutput<User> getUsers(@Valid DataTablesInput input) {
        return userRepository.findAll(input);
    }

Now i suspect DataTables itself.

i'm using DataTables 1.10.16

Update: It only worked when i opened it in my browser and saw data from controller from there, which was XML. But when i use Postman for example, it doesn't work.

If i explicitly declare that this method produces JSON, then it won't work in any way no matter how you bend it:

@JsonView(DataTablesOutput.View.class)
    @RequestMapping(value = "/users", method = RequestMethod.GET, produces = "application/json; charset=UTF-8")
    public DataTablesOutput<User> getUsers() {
        return userRepository.findAll(new DataTablesInput());
    }

Mapping to XML as i remember, was used in previous versions. Therefore, i assume that json mapper is not even using this feature.

darrachequesne commented 5 years ago

Hi, I'm not able to reproduce with GET or POST requests: https://github.com/darrachequesne/spring-data-jpa-datatables-sample/tree/issue-79

In both cases, only id, firstName and lastName are displayed.

RomanKurbanov commented 5 years ago

@darrachequesne Hi, thanks a lot for answering. I downloaded the branch and now am trying to reproduce the issue. The sample you provided works flawlessly, by the way.

RomanKurbanov commented 5 years ago

@darrachequesne Yeah, i reproduced it. The issue was in WebConfig - i used Jackson-datatype-hibernate5 as a MessageConverter in my WebConfig. Where can i show you modified sample project?

darrachequesne commented 5 years ago

Great! Could you please fork the repository, and push the branch with the failure on it?

RomanKurbanov commented 5 years ago

@darrachequesne https://github.com/iSosnitsky/spring-data-jpa-datatables-sample

darrachequesne commented 5 years ago

@iSosnitsky thanks for providing a way to reproduce! It seems you have to manually disable the DEFAULT_VIEW_INCLUSION (it is disabled by default in Spring Boot, but was enabled in your case):

class HibernateAwareObjectMapper extends ObjectMapper {
    public HibernateAwareObjectMapper() {
        Hibernate5Module module = new Hibernate5Module();
        module.disable(Hibernate5Module.Feature.USE_TRANSIENT_ANNOTATION);
        this.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
        this.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
+       this.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false);
        this.registerModule(module);
    }
}
RomanKurbanov commented 5 years ago

@darrachequesne Thanks, it works! Mind if i put that in your project's Wiki?

RomanKurbanov commented 5 years ago

By the way, if you declare a lazy loaded field as a non-searchable, it won't be initialized:

{
                    data: 'office.city',
                    render: function (data) { return data ? data : '-'; },
                    searchable: false
                }
darrachequesne commented 5 years ago

@iSosnitsky let's add that to the README, if you will.

Regarding the lazy-loaded field, it seems you are right! Would you mind opening a new issue for that?

RomanKurbanov commented 5 years ago

@darrachequesne Sure!

darrachequesne commented 4 years ago

Closed due to inactivity, please reopen if needed.