I'm on my way to create my first RESTful API with Spring-Hateoas and Spring-Boot. So far everything looks quite promising, but when I try to create resources within a class which extends ResourceAssemblerSupport by using the toResource() method ( by calling http://localhost:8080/myVariable/greeting), I get an IllegalArgumentException telling me that
Not enough variable values available to expand 'var'] with root cause
This only happens when I reference a @PathVariable on class level, which should be supported as far as I know.
My ControllerClass:
@RestController
@ExposesResourceFor(GreetingResource.class)
@RequestMapping("/{var}")
public class GreetingController {
@Autowired
private BeanFactory beanFactory;
@Autowired
private GreetingAssembler greetingAssembler;
private static final String TEMPLATE = "Hello, %s!";
@ResponseStatus(HttpStatus.OK)
@RequestMapping("/greeting")
public GreetingResource greeting( @PathVariable("var") String var ) {
GreetingEntity greetingEntity = beanFactory.getBean(GreetingEntity.class, String.format(TEMPLATE, var));
GreetingResource greeting = greetingAssembler.toResource(greetingEntity);
greeting.add(linkTo(methodOn(GreetingController.class).greeting(var)).withSelfRel());
return greeting;
}
}
My ResourceAssembler class seems to be at fault
@Service
public class GreetingAssembler extends ResourceAssemblerSupport<GreetingEntity, GreetingResource> {
@Autowired
private BeanFactory beanFactory;
/**
* constructor must call super to define which controller to link to
* and to define the resource
*/
public GreetingAssembler() {
super(GreetingController.class, GreetingResource.class);
}
/**
* based on configuration, build the resource
*
* @param entity
* @return
*/
@Override
public GreetingResource toResource(GreetingEntity entity) {
GreetingResource resource = createResourceWithId( entity.getId(),
entity);
return resource;
}
/**
* same as the method in ResourceAssemblerSupport, overwritten to evaluate the problem
*
* @param id
* @param entity
* @param parameters
* @return
*/
@Override
protected GreetingResource createResourceWithId(Object id, GreetingEntity entity, Object... parameters) {
Assert.notNull(entity);
Assert.notNull(id);
GreetingResource instance = instantiateResource(entity);
ControllerLinkBuilder builder = linkTo(GreetingController.class, parameters);
builder = builder.slash(id);
Link link = builder.withSelfRel();
instance.add(link);
return instance;
}
/**
* overwrite the default method to be able to call the class from aplicationcontext with params
*
* @param entity
* @return
*/
@Override
protected GreetingResource instantiateResource(GreetingEntity entity) {
return beanFactory.getBean(GreetingResource.class, entity.getContent());
}
}
The GreetingResource and GreetingEntity are simple POJOs.
The whole sourcecode is available at https://github.com/r0bse/Spring-Hateoas-ResourceAssemblerSupport-Problem and is based on a simple example: https://github.com/spring-guides/gs-rest-hateoas
My Question is: Am I doing something wrong, is it a bug or is my understanding how everything works together not good enough?