we have a working asynchronous REST API with Spring Boot and Hateoas:
@RestController
@EnableAutoConfiguration
@RequestMapping("/metfrag/api/v1")
/** @RequestMapping("${metfragrest-controller.path}") Fail in linkTo() **/
public class MetFragRestController {
...
@RequestMapping(method = RequestMethod.POST, value = "", ...)
@ResponseBody
public ResponseEntity<Resource<ProcessAssembler>> process(...) {
...
linkTo(MetFragRestController.class).slash("status").slash(processid);
...
}
}
The linkTo()
is needed to return the URL where to poll for the job status.
This breaks if I provide the base URL from an application.properties
value: @RequestMapping("${metfragrest-controller.path}")
. The linkTo()
calls o.s.hateoas.mvc.ControllerLinkBuilder.linkTo()
, which uses o.s.web.util.UriComponents.expand()
and fails in o.s.web.util.UriComponents$VarArgsTemplateVariables.getValue()
.
What I need is the call
resource.add(linkTo(MetFragRestController.class).slash("status").slash(processid).withRel("status"));
to return something like
http://localhost:8090/metfrag/api/v1/status/java_io_tmpdir5547995162586347505
Any ideas what to try next ?
Thanks in advance,
yours, Steffen
If needed, full code is available from MetFragRestController.java
Full java trace:
2023-06-21 12:32:51.457 ERROR 1 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.IllegalArgumentException: Not enough variable values available to expand 'metfragrest-controller.path'] with root cause
java.lang.IllegalArgumentException: Not enough variable values available to expand 'metfragrest-controller.path'
at org.springframework.web.util.UriComponents$VarArgsTemplateVariables.getValue(UriComponents.java:329) ~[spring-web-4.3.11.RELEASE.jar!/:4.3.11.RELEASE]
at org.springframework.web.util.UriComponents.expandUriComponent(UriComponents.java:232) ~[spring-web-4.3.11.RELEASE.jar!/:4.3.11.RELEASE]
at org.springframework.web.util.HierarchicalUriComponents$FullPathComponent.expand(HierarchicalUriComponents.java:688) ~[spring-web-4.3.11.RELEASE.jar!/:4.3.11.RELEASE]
at org.springframework.web.util.HierarchicalUriComponents.expandInternal(HierarchicalUriComponents.java:331) ~[spring-web-4.3.11.RELEASE.jar!/:4.3.11.RELEASE]
at org.springframework.web.util.HierarchicalUriComponents.expandInternal(HierarchicalUriComponents.java:48) ~[spring-web-4.3.11.RELEASE.jar!/:4.3.11.RELEASE]
at org.springframework.web.util.UriComponents.expand(UriComponents.java:165) ~[spring-web-4.3.11.RELEASE.jar!/:4.3.11.RELEASE]
at org.springframework.web.util.UriComponentsBuilder.buildAndExpand(UriComponentsBuilder.java:360) ~[spring-web-4.3.11.RELEASE.jar!/:4.3.11.RELEASE]
at org.springframework.web.util.DefaultUriTemplateHandler.expandAndEncode(DefaultUriTemplateHandler.java:147) ~[spring-web-4.3.11.RELEASE.jar!/:4.3.11.RELEASE]
at org.springframework.hateoas.mvc.ControllerLinkBuilder$CustomUriTemplateHandler.expandAndEncode(ControllerLinkBuilder.java:340) ~[spring-hateoas-0.23.0.RELEASE.jar!/:na]
at org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo(ControllerLinkBuilder.java:122) ~[spring-hateoas-0.23.0.RELEASE.jar!/:na]
at org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo(ControllerLinkBuilder.java:102) ~[spring-hateoas-0.23.0.RELEASE.jar!/:na]
at de.ipbhalle.metfragrest.MetFragRestController.process(MetFragRestController.java:119) ~[classes!/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-4.3.11.RELEASE.jar!/:4.3.11.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133) ~[spring-web-4.3.11.RELEASE.jar!/:4.3.11.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97) ~[spring-webmvc-4.3.11.RELEASE.jar!/:4.3.11.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) ~[spring-webmvc-4.3.11.RELEASE.jar!/:4.3.11.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) ~[spring-webmvc-4.3.11.RELEASE.jar!/:4.3.11.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) ~[spring-webmvc-4.3.11.RELEASE.jar!/:4.3.11.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967) ~[spring-webmvc-4.3.11.RELEASE.jar!/:4.3.11.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901) ~[spring-webmvc-4.3.11.RELEASE.jar!/:4.3.11.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) ~[spring-webmvc-4.3.11.RELEASE.jar!/:4.3.11.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872) ~[spring-webmvc-4.3.11.RELEASE.jar!/:4.3.11.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:661) ~[tomcat-embed-core-8.5.20.jar!/:8.5.20]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) ~[spring-webmvc-4.3.11.RELEASE.jar!/:4.3.11.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) ~[tomcat-embed-core-8.5.20.jar!/:8.5.20]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-8.5.20.jar!/:8.5.20]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.20.jar!/:8.5.20]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) ~[tomcat-embed-websocket-8.5.20.jar!/:8.5.20]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.20.jar!/:8.5.20]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.20.jar!/:8.5.20]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) ~[spring-web-4.3.11.RELEASE.jar!/:4.3.11.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.11.RELEASE.jar!/:4.3.11.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.20.jar!/:8.5.20]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.20.jar!/:8.5.20]
at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:108) ~[spring-web-4.3.11.RELEASE.jar!/:4.3.11.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.11.RELEASE.jar!/:4.3.11.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.20.jar!/:8.5.20]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.20.jar!/:8.5.20]
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81) ~[spring-web-4.3.11.RELEASE.jar!/:4.3.11.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.11.RELEASE.jar!/:4.3.11.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.20.jar!/:8.5.20]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.20.jar!/:8.5.20]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) ~[spring-web-4.3.11.RELEASE.jar!/:4.3.11.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.11.RELEASE.jar!/:4.3.11.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.20.jar!/:8.5.20]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.20.jar!/:8.5.20]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) ~[tomcat-embed-core-8.5.20.jar!/:8.5.20]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) ~[tomcat-embed-core-8.5.20.jar!/:8.5.20]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478) ~[tomcat-embed-core-8.5.20.jar!/:8.5.20]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) ~[tomcat-embed-core-8.5.20.jar!/:8.5.20]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80) ~[tomcat-embed-core-8.5.20.jar!/:8.5.20]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) ~[tomcat-embed-core-8.5.20.jar!/:8.5.20]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) ~[tomcat-embed-core-8.5.20.jar!/:8.5.20]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799) ~[tomcat-embed-core-8.5.20.jar!/:8.5.20]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) ~[tomcat-embed-core-8.5.20.jar!/:8.5.20]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) ~[tomcat-embed-core-8.5.20.jar!/:8.5.20]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1457) ~[tomcat-embed-core-8.5.20.jar!/:8.5.20]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-8.5.20.jar!/:8.5.20]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-8.5.20.jar!/:8.5.20]
at java.base/java.lang.Thread.run(Thread.java:829) ~[na:na]