I'm getting the following error when calling ControllerLinkBuilder.linkTo
from a websocket.
java.lang.IllegalStateException: Could not find current request via RequestContextHolder
at org.springframework.util.Assert.state(Assert.java:385)
at org.springframework.hateoas.mvc.ControllerLinkBuilder.getCurrentRequest(ControllerLinkBuilder.java:234)
at org.springframework.hateoas.mvc.ControllerLinkBuilder.getBuilder(ControllerLinkBuilder.java:186)
at org.springframework.hateoas.mvc.ControllerLinkBuilderFactory.linkTo(ControllerLinkBuilderFactory.java:117)
at org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo(ControllerLinkBuilder.java:135)
at urlshortener2014.common.web.UrlShortenerController.createAndSaveIfValid(UrlShortenerController.java:94)
at urlshortener2014.richcarmine.web.UrlShortenerControllerWithLogs.access$200(UrlShortenerControllerWithLogs.java:45)
at urlshortener2014.richcarmine.web.UrlShortenerControllerWithLogs$CreateCallable.call(UrlShortenerControllerWithLogs.java:226)
at urlshortener2014.richcarmine.massiveShortenerNaiveWS.ShortURLWSGenerator.onCall(ShortURLWSGenerator.java:41)
at urlshortener2014.richcarmine.massiveShortenerNaiveWS.ShortURLWSGenerator.onCall(ShortURLWSGenerator.java:15)
at urlshortener2014.richcarmine.massiveShortenerREST.RequestContextAwareCallable.call(RequestContextAwareCallable.java:26)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
The whole project is about shortening urls, as my first approach with spring websockets I'm trying to get it work just by answering back the shortened url from any url.
My TextWebSocketHandler
public class MyHandler extends TextWebSocketHandler {
AtomicLong messageOrder = new AtomicLong(0);
ExecutorService threadPool = Executors.newCachedThreadPool();
CompletionService<CSVContent> pool = new ExecutorCompletionService<>(threadPool);
/* controller reference */
@Autowired
UrlShortenerControllerWithLogs controller;
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
logger.info("WS: " + message.getPayload());
long order = messageOrder.getAndIncrement();
pool.submit(new ShortURLWSGenerator(order,message.getPayload(),"","","",session.getRemoteAddress(),controller));
CSVContent content = pool.take().get();
session.sendMessage(new TextMessage("Echo Test: " + content.getShortURL().getUri()));
}
}
Here is ShortURLWSGenerator
public class ShortURLWSGenerator extends RequestContextAwareCallable<CSVContent>{
...
@Override
public CSVContent onCall() {
ShortURL shortURL = null;
try {
shortURL = controller. new CreateCallable(url,sponsor,brand,owner,address.toString()).call();
} catch (Exception e) {
e.printStackTrace();
}
CSVContent content = new CSVContent();
content.setOrder(order);
content.setShortURL(shortURL);
return content;
}
}
Used RequestContextAwareCallable which solved the same problem when implementing the same functionlity as a REST service, in any case I'm still getting the same error even with a simple Callable.
Here is CreateCallable that just wraps the main function
public class CreateCallable implements Callable<ShortURL>{
...
@Override
public ShortURL call() throws Exception {
/* explodes while creating the new short url */
return createAndSaveIfValid(url,sponsor,brand,owner,ip);
}
}
Finally here is createAndSaveIfValid
which calls ControllerLinkBuilder.linkTo
protected ShortURL createAndSaveIfValid(String url, String sponsor,
String brand, String owner, String ip) {
UrlValidator urlValidator = new UrlValidator(new String[] { "http",
"https" });
if (urlValidator.isValid(url)) {
String id = Hashing.murmur3_32()
.hashString(url, StandardCharsets.UTF_8).toString();
ShortURL su = new ShortURL(id, url,
linkTo(
methodOn(UrlShortenerController.class).redirectTo(
id, null)).toUri(), sponsor, new Date(
System.currentTimeMillis()), owner,
HttpStatus.TEMPORARY_REDIRECT.value(), true, ip, null);
return shortURLRepository.save(su);
} else {
return null;
}
}
The complete project can be found here on github