Consuming Spring Hatesoas Restservice with RestTemplate

I have two applications: one is called bar , which gives me resources in HAL format. Another is bcm to use this service.

An example of a bar response is as follows:

[ { "name":"Brenner/in", "_links":{ "self":{ "href":"..host/bbsng-app-rest/betrieb/15" } } }, { "name":"Dienstleistungshelfer/in HW", "_links":{ "self":{ "href":"..host/bbsng-app-rest/betrieb/4" } } }, { ... 

Now I'm trying to use this from bcm using Spring RestTemplate. My solution works, but I'm not very happy with this solution, and I think there is a cleaner way.

My client code consuming RestService looks like this:

 @Autowired private RestTemplate template; @Override @SuppressWarnings("unchecked") public BerufListe findeAlleBerufe() { final BerufListe berufListe = new BerufListe(); final ResponseEntity<List> entity = template.getForEntity(LinkUtils.findBeruf(), List.class); if (OK.equals(entity.getStatusCode())) { final List<LinkedHashMap> body = entity.getBody(); for (final LinkedHashMap map : body) { final LinkedHashMap idMap = (LinkedHashMap) map.get("_links"); String id = remove(String.valueOf(idMap.get("self")), "href="); id = remove(id, "{"); id = remove(id, "}"); final String name = String.valueOf(map.get("name")); final Beruf beruf = new Beruf(id, name); berufListe.add(beruf); } } return berufListe; } 

There are some ugly code, as you see. One of them is that I do not have any generics for my collections. Otherwise, I get the Resource_ID very complex, and I use StringUtils.remove many times to extract my own URL.

I am sure there should be a more convenient way to use HAL-Response on Spring.

Thanks.

+6
source share
1 answer

See the Resource class from spring-hateaos.

It provides methods for extracting links from a response. However, since RestTemplate requires you to provide the class as a variable, I have not found any other way than subclassing the desired object and using it for RestTemplate.

Then you can look like this:

 public class BerufResource extends Resource<Beruf> { } BerufResource resource = template.getForEntity("http://example.at/berufe/1", BerufResource.class); Beruf beruf = resource.getContent(); // do something with the entity 

If you want to request a complete list, you need to pass the version of your array to RestTemplate:

 BerufResource[] resources = template.getForEntity("http://example.at/berufe", BerufResource[].class); List<BerufResource> berufResources = Arrays.asList(resources); for(BerufResource resource : berufResources) { Beruf beruf = resource.getContent(); } 

Unfortunately, we cannot write Resource<Beruf>.class , which defeats the whole purpose of the universal class, since we need to again create a subclass for each object. The reason for this is the erasure of styles. I read somewhere that they plan to introduce general support for RestTemplate, but I don't know any details.

Address retrieval of identifier from URL:

I would recommend using a different client-side model and replacing the type of the id field with a string and storing the entire URL in it. Thus, you can easily restore the entire object whenever you want, and you do not need to create URLs yourself. In any case, you will need the URL later if you plan to send POST requests to your API, as spring -hateaos requires you to send a link instead of an identifier. A typical POST request might look like this:

 { "firstname": "Thomas", "nachname": "Maier", "profession": "http://example.at/professions/1" } 
+3
source

Source: https://habr.com/ru/post/980432/


All Articles