0

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?

Robert Schröder
  • 169
  • 2
  • 11

0 Answers0