Long Polling with Spring's DeferredResult
Asked Answered
U

1

12

The client periodically calls an async method (long polling), passing it a value of a stock symbol, which the server uses to query the database and return the object back to the client.

I am using Spring's DeferredResult class, however I'm not familiar with how it works. Notice how I am using the symbol property (sent from client) to query the database for new data (see below).

Perhaps there is a better approach for long polling with Spring?

How do I pass the symbol property from the method deferredResult() to processQueues()?

    private final Queue<DeferredResult<String>> responseBodyQueue = new ConcurrentLinkedQueue<>();

    @RequestMapping("/poll/{symbol}")
    public @ResponseBody DeferredResult<String> deferredResult(@PathVariable("symbol") String symbol) {
        DeferredResult<String> result = new DeferredResult<String>();
        this.responseBodyQueue.add(result);
        return result;
    }

    @Scheduled(fixedRate=2000)
    public void processQueues() {
        for (DeferredResult<String> result : this.responseBodyQueue) {
           Quote quote = jpaStockQuoteRepository.findStock(symbol);
            result.setResult(quote);
            this.responseBodyQueue.remove(result);
        }
    }
Ultrasonic answered 16/7, 2015 at 15:47 Comment(1)
Do you want to wait for the result and return it to the client? If not, just return null. If yes, you probably better use a Future because you can extract the result from the submitting thread afterwards.Tapestry
T
15

DeferredResult in Spring 4.1.7:

Subclasses can extend this class to easily associate additional data or behavior with the DeferredResult. For example, one might want to associate the user used to create the DeferredResult by extending the class and adding an additional property for the user. In this way, the user could easily be accessed later without the need to use a data structure to do the mapping.

You can extend DeferredResult and save the symbol parameter as a class field.

static class DeferredQuote extends DeferredResult<Quote> {
    private final String symbol;
    public DeferredQuote(String symbol) {
        this.symbol = symbol;
    }
}

@RequestMapping("/poll/{symbol}")
public @ResponseBody DeferredQuote deferredResult(@PathVariable("symbol") String symbol) {
    DeferredQuote result = new DeferredQuote(symbol);
    responseBodyQueue.add(result);
    return result;
}

@Scheduled(fixedRate = 2000)
public void processQueues() {
    for (DeferredQuote result : responseBodyQueue) {
        Quote quote = jpaStockQuoteRepository.findStock(result.symbol);
        result.setResult(quote);
        responseBodyQueue.remove(result);
    }
}
Theocracy answered 22/7, 2015 at 4:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.