David Melia opened SPR-17485 and commented

Hi,

org.springframework.messaging.simp.broker.DefaultSubscriptionRegistry contains

private static EvaluationContext messageEvalContext =
          SimpleEvaluationContext.forPropertyAccessors(new SimpMessageHeaderPropertyAccessor()).build();

but with no way to override it.

If you think about a stock broking site contain 1000s of price updates I need the ability to add a selector header to filter only the stocks that the customer is interested in. To do that using the default cut down EvaluationContext the selector would be very clunky.

If I can add my own function to the evaluation context i.e

messageEvalContext.setVariable("myCustomStockSymbolFilterFunction" . . .

then the selector would be simplified i.e.

#myCustomStockSymbolFilterFunction(headers['simpDestination'],{'MSFT','BARC'})

Therefore: * Could you add the ability to override the EvaluationContext? 

  • If so would it be possible to make SimpMessageHeaderPropertyAccessor available somehow?

Thanks


Affects: 5.1.2

Comment From: spring-projects-issues

Juergen Hoeller commented

In order to preserve the common SimpMessageHeaderPropertyAccessor for those purposes, maybe a template method along the lines of protected void customizeEvaluationContext would make sense, not replacing the default setup but just adding variables to it? Do you see any further need for a custom EvaluationContext instance, potentially switching to a StandardEvaluationContext or the like?

Comment From: spring-projects-issues

David Melia commented

It is possible that others may want full control but for my own needs a template sounds great as long as I can add a custom function

messageEvalContext.setVariable("myCustomStockSymbolFilterFunction" . . .

Thanks Juergen.

Comment From: spring-projects-issues

Rossen Stoyanchev commented

David Melia, I'm wondering if you considered destination patterns as a way for subscribers to narrow what they're interested in? Like in the spring-portfolio sample, subscribing and broadcasting.

Comment From: spring-projects-issues

David Melia commented

Hi Rossen Stoyanchev

Thanks for the spring-portfolio sample which is providing the basis of my prototype but I noticed that all prices are being pushed back to the browser regardless if that user has them or not which would be a problem for us. 

My requirement is to provide streaming prices for thousands of stocks from around the world. Customers will have a mixed portfolio and we don't want to segment it into UK, US, Canada, etc. This is why I struggled to narrow the subscription for this type of stock.  I could either 1. Have a topic per instrument i.e. /topic/price.stock.MSFT, /topic/price.stock.BARC, /topic/price.stock.AZN, etc 2. Have a topic for all instruments /topic/price.stock.* but filter with a selector.

I thought 2 was the best approach which is when I noticed that I needed to raise this issue.

Any thoughts are welcome :)

Thanks

Comment From: spring-projects-issues

Rossen Stoyanchev commented

Yes the sample was meant to show 1) with "topic per instrument". At any given time the broker has as many topics as the number of instruments in the portfolios of connected customers, which perhaps won't be as many as all the stocks that exist.

Another option to consider would be to create an individual queue for each customer portfolio. The code pushing stock updates could then check which users are connected through the SimpUserRegistry and push updates to the queues of those whose portfolios contain a stock.

Comment From: spring-projects-issues

David Melia commented

That's interesting. Let's say each customer has 100 unique instruments on screen at any one time. Also assume that we keep the topic /topic/price.stock.*

I thought creating 100 stomp JS instrument subscriptions from the browser would be the wrong thing to do i.e using your prototype I would do something like

// controller.js            

      tradeService.connect("/portfolio") 

. . . .

                angular.forEach($scope.positions, function(value, key){
                    tradeService.fetchQuoteStream(key).then(null, null,
                            function(quote) {
                                processQuote(quote);
                            }
                        );
                });

Rossen Stoyanchev  Is the above multiple Stomp JS subscription the recommended way to achieve instrument subscriptions than the message selector way?  Would there be a performance cost?

Thanks

Comment From: spring-projects-issues

Rossen Stoyanchev commented

David Melia it's difficult to say that generally, because the answer will vary based on number of customers x tickers, as well as usage patterns, but I wouldn't discount this as an option.

DefaultSubscriptionRegistry maintains a cache of previously matched subscription destinations. By default that's set to 1024, but you can configure it in the Java config through the MessageBrokerRegistry. If the lookups are cached, I don't think the rest is very different since you have to deliver a message per picker regardless how the subscriptions are laid out.