Javan
Javan

Reputation: 189

How to change Hateoas output format in spring application?

I am currently working on a spring application that offers a REST interface with which CRUD operations on entities of various kinds can be performed. These entities are stored in repositories and thus a major part of the REST interface is automatically generated by spring. When I execute a GET request on such an entity type (e.g. /devices), the result looks as following:

{  
"_embedded":{  
    "devices":[  
        {  
            "macAddress": "...",
            "ipAddress": "...",
            "name": "Device_1",
            "id":"5c866db2f8ea1203bc3518e8",
            "_links":{  
                "self":{  
                    ...
                },
            "device":{  
                ...
            }
        }, ...
    ]
},
"_links":{  
    ...
},
"page":{  
        "size":20,
        "totalElements":11,
        "totalPages":1,
        "number":0
    }
}

Now I need to implement a similar interface manually, because additional checks are required. I have made use of the spring-hateoas features for this purpose. However, I am unable to achieve the same output structure like the one automatically generated by spring. The corresponding code in my controller class (annotated with RestController) looks as follows:

@GetMapping("/devices")
public Resources<Device> getDevices() {
    List<Device> deviceList = getDeviceListFromRepository();

    Link selfRelLink = ControllerLinkBuilder.linkTo(
            ControllerLinkBuilder.methodOn(RestDeviceController.class)
                    .getDevices())
            .withSelfRel();

    Resources<Device> resources = new Resources<>(deviceList);
    resources.add(selfRelLink);

    return resources;
}

The configuration (excerpt) looks as follows:

@Configuration
@EnableWebMvc
@EnableSpringDataWebSupport
@EnableHypermediaSupport(type = EnableHypermediaSupport.HypermediaType.HAL)
public class WebServletConfiguration extends WebMvcConfigurerAdapter implements ApplicationContextAware {
...
    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer c) {
        c.defaultContentType(MediaTypes.HAL_JSON);
    }
...
}

However, this is the output of a request:

{  
   "links":[  
      {  
         "rel":"self",
         "href":"..."
      }
   ],
   "content":[  
      {  
         "id":"5c866db2f8ea1203bc3518e8",
         "name":"Device_1",
         "macAddress": "...",
         "ipAddress":"...",
      }
   ]
}

As you can see, instead of an _embedded key there is a content key and the links key misses the leading underscore. These are the main issues I have with this output, more detailed differences compared to the output above are not that important to me. I would like to unify the ouput generated by my application, but I am unable to achieve the output format of the mappings that are automatically generated by spring. I also tried to wrap the resources object into another resource object (like return new Resource<...>(resources)), this did not work as well though.

Do you have any hints for me about what I am doing wrong here? I am quite new to Spring & Co, so please tell me if you need more information about a certain thing. Any help is highly appreciated. Thanks in advance!

Upvotes: 0

Views: 271

Answers (1)

Javan
Javan

Reputation: 189

Finally I was able to find a solution: The strange output format as showed in the question was generated due to the accept header application/json that was sent by the client. After adding

@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
    configurer.ignoreAcceptHeader(true);
    configurer.defaultContentType(MediaTypes.HAL_JSON);
}

to class WebServletConfiguration which extends WebMvcConfigurerAdapter everything works as exptected and the output format is now HAL-like. A quite easy fix, but it took me weeks to figure this out. Maybe this answer will help somebody else in the future.

Upvotes: 1

Related Questions