Spring specifications 'and' not working
Asked Answered
O

1

6

hello! I'm trying to build a custom filter for a data grid at runtime. I'm using spring boot and vaadin 8 for data presentation. Vaadin knowledge is irrelevant to this question.

How i'm doing: I built a hashmap for the filters.

private HashMap<String, Specification<ARInteraction>> interactionSpecifications =
                                                                new HashMap<>();

Each filter text field adds or removes a specification to the map:

TextField filterOwner = new TextField("Filter");
    filterOwner.addValueChangeListener(nv -> {
        if (StringUtils.isNotEmpty(nv.getValue())) {
            interactionSpecifications.put("owner", ARInteractionSpecifications
                             .withOwnerEmail(nv.getValue()));
        } else {
            interactionSpecifications.remove("owner");
        }
        refreshContent();
    });

When the field data changes, a custom specification is added or substituted (or removed) from the specifications map.

Then I call to refresh the data view content, which causes the query to fetch data to be run.

To build the specification to query the data, I simply add all specifications by applying an 'and' operation between them.

private Specification<ARInteraction> buildSpecification() {
    // No specs
    if (interactionSpecifications.isEmpty())
        return null;

    // Assembles all specs together
    Specification<ARInteraction> ret = null;
    for (Specification<ARInteraction> spec : interactionSpecifications.values()) {
        if (ret == null) {
            ret = Specification.where(spec);
        } else {
            ret.and(spec);
        }
    }
    return ret;
}

What I expected to happen is that, with both filters applied, only entites that comply with both specifications are fetched.

What actually happens is that if I set the status specification alone (not shown here) it works, if I set the owner email filter it also works, but if I set both, all interactions from that owner are shown ignoring the status filter.

Obvious answered 7/6, 2018 at 22:22 Comment(0)
O
11

how are you?

Specification behaviour is immutable, so you should be assigning the ret specification with the and operation. Beginner mistake.

for (Specification<ARInteraction> spec : interactionSpecifications.values()) {
    if (ret == null) {
        ret = Specification.where(spec);
    } else {
        ret = ret.and(spec); //Assign the ret so that specs are actually added.
    }
}
Obvious answered 8/6, 2018 at 17:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.