Spring Data REST returns EmptyCollectionEmbeddedWrapper instead of empty collection

Viewed 706

I am developing a Service based on Spring Data REST. Cause of the fact that we are creating the frontend code using swagger (generated via SpringFox) I had to deactivate the return of the HAL-format which works fine with one exception.

If the result of a request is an empty list the response looks like this

{
"links": [
    {
        "rel": "self",
        "href": "http://localhost:9999/users"
    },
    {
        "rel": "profile",
        "href": "http://localhost:9999/profile/users"
    }
],
"content": [
    {
        "rel": null,
        "collectionValue": true,
        "relTargetType": "com.example.User",
        "value": []
    }
]
}

How can I get an empty List as content?

2 Answers

I have had to adapt the solution provided in the previous solution to use the types introduced by the Spring HATEOAS 1.x

This is the code I'm using:

@Component
public class ResourceProcessorEmpty implements RepresentationModelProcessor<CollectionModel<Object>> {
    @Override
    public CollectionModel<Object> process(CollectionModel<Object> resourceToThrowAway) {
        if (resourceToThrowAway.getContent().size() != 1) {
            return resourceToThrowAway;
        }
        if (!resourceToThrowAway.getContent().iterator().next().getClass().getCanonicalName().contains("EmptyCollectionEmbeddedWrapper")) {
            return resourceToThrowAway;
        }

        CollectionModel<Object> newResource = new CollectionModel<>(Collections.emptyList());
        newResource.add(resourceToThrowAway.getLinks());
        return newResource;
    }
}

The best and easiest solution i found finally for this so far is the following. Implement a custom ResourceProcessor, which is automatically picked up and used by spring(because of the @Component). Override the process method and in the method return a new Resource() which is initialized with an empty list, instead of the old Resource you got as an argument, add the links and all what you want and that's it. Like this:

import java.util.Collections;
import javax.servlet.http.HttpServletRequest;
import org.springframework.hateoas.Link;
import org.springframework.hateoas.ResourceProcessor;
import org.springframework.hateoas.Resources;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

@Component
public class ResourceProcessorEmpty implements ResourceProcessor<Resources<Object>>
{
    @Override
    public Resources<Object> process(final Resources<Object> resourceToThrowAway)
    {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();

// In my case i needed the request link with parameters, and the empty content[] array

        Link link = new Link(request.getRequestURL().toString() + "?" + request.getQueryString());
        Resources<Object> newResource = new Resources<>(Collections.emptyList());
        newResource.add(link);
        return newResource;
    }
}

For clarification: if you use Resources<Object>, that will handle empty collections(when that "EmptyCollectionEmbeddedWrapper" dummy object would be returned), whereas Resources<Resource<Object>> will handle non-empty collections. In this case the first needs to be used.

Related