The setup: So I have a RESTfull API written in java, using spring-boot
and spring-hates
for adding links to the resource (Hypermedia-Driven RESTful Web Service). Everything I have is standard and no additional settings or changes are made
The problem
- Case: no links on resource - Chrome TTFB avg. (10 runs) 400ms for 1000 items
- Case: 1 self reference link on resource - Chrome TTFB avg. (10 runs) 1500ms for 1000 items
I am using this official guide
The question
Why adding only 1 link to my resource adds additional 1 second for the processing the request. I will need around 5 - 7 links on each resource and every resource has additional embedded ones?
For 9000 total items with only 1 link per item (included the nested ones), i have to wait 30 sec for the response and without links ~ 400 ms.
P.S. The additional code is irrelevant because I am just adding a code from the tutorial which effects the performance dramatically.
Edit 1
As suggested I am adding example code from my TextItem
constructor
add(linkTo(methodOn(TestController.class).getTestItems()).withRel("testLink"));
Edit 2
So the following example proposed from @Mathias Dpunkt works absolutely perfect
private Method method = ReflectionUtils.findMethod(TestController.class, "getOne", Integer.class);
@Override
public Resource<Item> process(Resource<Item> resource) {
resource.add(linkTo(method, resource.getContent().getId()).withSelfRel());
return resource;
}
The new problem
Controller:
@RestController
@RequestMapping("items")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class TestController {
private final ItemResourceProcessor resourceProcessor;
@RequestMapping(method = GET)
public ResponseEntity<List<Resource<Item>>> getAll() {
List<Resource<Item>> items = new ArrayList<>(100);
for (int i = 0; i < 100; i++) {
items.add(resourceProcessor.process(
new Resource<>(new Item(i, UUID.randomUUID().toString()))));
}
return ResponseEntity.ok(items);
}
@RequestMapping(method = GET, path = "/{id}")
public ResponseEntity<Resource<Item>> getOne(@PathVariable Integer id, @RequestParam boolean test1, @RequestParam boolean test2) {
return null;
}
}
If the controller method takes @RequestParam
the posted solution does not append it to the link. When I call
private Method method = ReflectionUtils.findMethod(TestController.class, "getOne", Integer.class);
@Override
public Resource<Item> process(Resource<Item> resource) {
resource.add(linkTo(method, resource.getContent().getId(), true, true).withSelfRel());
return resource;
}
methodOn
. But as long as you believe that it's not necessary to show your code we can't help you. – MedicablelinkTo(TestController.class).withRel("testLink")
. If necessary you can add an ID (or another path segment) usinglinkTo(TestController.class).slash(id)
.methodOn
is quite costly. – MedicablemethodOn()
being expensive, then a profiler would show it. You're saying that you don't have the "time" to explain, but you would've saved a lot more time by taking my advice immediately in that case. If you can't explain why profiling is out of the question, then I can only assume that you don't really understand what I was suggesting. After all, it's the first thing to do if you have performance problems. – Lampley