Переменная пути на уровне класса контроллера не работает Spring Restful

У меня есть контроллер, где у меня есть отображение уровня контроллера как "/subject /{subjectId}/ уроки", который необходим по какой-то причине

@RestController
@RequestMapping( value = "/subjects/{subjectId}/lessons",produces = { MediaType.APPLICATION_JSON_VALUE } )
public class LessonController {
    .......
    @RequestMapping( method = RequestMethod.GET )
    public ResponseEntity<Resources<Resource<Lesson>>> getAllSjubject(@PathVariable(value = "subjectId") int subjectId){        

        List<Lesson> lessonList = lessonService.getAllLessons(subjectId);
        Resources<Resource<Lesson>> resource = this.lessonResourceAssembler.toLessonResourceList(lessonList);
        return new ResponseEntity<Resources<Resource<Lesson>>>(resource, HttpStatus.OK);
    }
}

Когда сделан запрос, он выдает исключение

java.lang.IllegalArgumentException: Not enough variable values available to expand 'subjectId'
    at org.springframework.web.util.UriComponents$VarArgsTemplateVariables.getValue(UriComponents.java:327)
    at org.springframework.web.util.UriComponents.expandUriComponent(UriComponents.java:230)
    at org.springframework.web.util.HierarchicalUriComponents$FullPathComponent.expand(HierarchicalUriComponents.java:685)
    at org.springframework.web.util.HierarchicalUriComponents.expandInternal(HierarchicalUriComponents.java:328)
    at org.springframework.web.util.HierarchicalUriComponents.expandInternal(HierarchicalUriComponents.java:47)
    at org.springframework.web.util.UriComponents.expand(UriComponents.java:163)
    at org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo(ControllerLinkBuilder.java:89)
    at org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo(ControllerLinkBuilder.java:69)
    at com.khaino.springrest.assembler.LessonResourceAssembler.toLessonResource(LessonResourceAssembler.java:31)
    at com.khaino.springrest.assembler.LessonResourceAssembler.toLessonResourceList(LessonResourceAssembler.java:44)
    at com.khaino.springrest.controller.LessonController.getAllSjubject(LessonController.java:43)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:111)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:806)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:729)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:673)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1526)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1482)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Unknown Source)

Но когда я перемещаю переменную пути к уровню метода, как показано ниже, она работает правильно.

@RequestMapping( value = "/subjects",produces = { MediaType.APPLICATION_JSON_VALUE } )
public class LessonController {

    ......

    @RequestMapping( value = "/{subjectId}/lessons", method = RequestMethod.GET )
    public ResponseEntity<Resources<Resource<Lesson>>> getAllSjubject(@PathVariable("subjectId") int subjectId){        

        List<Lesson> lessonList = lessonService.getAllLessons(subjectId);
        Resources<Resource<Lesson>> resource = this.lessonResourceAssembler.toLessonResourceList(lessonList);
        return new ResponseEntity<Resources<Resource<Lesson>>>(resource, HttpStatus.OK);
    }

    ....
}

Что-то не так с моим кодом? В чем может быть причина и решение?

2 ответа

Решение

Ваши сопоставления работают в обоих сценариях, но на основе трассировки стека источником проблемы является следующая часть:

this.lessonResourceAssembler.toLessonResourceList(lessonList)

Вы создаете некоторые Hypermedia Links который содержит некоторые Template Variables которые НЕ расширены.

Обновлено: используйте этот подход для создания ссылки:

linkTo(methodOn(LessonController.class).getAllSjubject(42))
                .withRel(REL_SELF)

mehtodOn в org.springframework.hateoas.mvc.ControllerLinkBuilder пакет, убедитесь, что у вас есть правильный статический импорт.

http://localhost:8080/springexample/subjects/3/lessons работал для меня с кодом:

import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping(value = "/subjects/{subjectId}/lessons", produces = { MediaType.APPLICATION_JSON_VALUE })
public class LessonController {
    @RequestMapping(method = RequestMethod.GET)
    public ResponseEntity getAllSjubject(
            @PathVariable(value = "subjectId") int subjectId) {
        System.out.println(subjectId);
        return new ResponseEntity(HttpStatus.OK);
    }
}

Имея, Spring Dependency определяется в pom.xml как: <spring.version>4.1.4.RELEASE</spring.version>

Другие вопросы по тегам