34

I'd like to synchronize the state to all the clients interested in particular entity changes. So I'd like to achieve something like:

  • exposing CRUD API on entity (via HTTP/REST and websockets)
  • and routing the response (of the modifying calls) to websockets topic

So technically, I'd be interested in ideas to mix spring-data-rest with spring websockets implementation to achieve something like spring-data-websocket.

There are a two solutions coming to my mind, and in fact both would be:

  • spring-data-rest to expose my entities via REST/HTTP API
  • websocket controllers (used for the modification calls on entities)

The websocket controllers would look like this:

@Controller
public class EntityAWebSocketController {
      @MessageMapping("/EntityA/update")
      @SendTo("/topic/EntityA/update")
      public EntityA update(EntityA entityA) throws Exception {
           // persist,....
           return entityA;
     }
}

Scenario 1: Websocket API called from REST/HTTP API

Rules:

  • client request is always REST/HTTP API
  • response is REST/HTTP API for all the operations
  • moreover for modifying operations the websocket message comes as well

Technically, could be achieved, by:

  • calling the websocket controllers from the spring-rest-data events (namely in the AfterCreateEvent, AfterSaveEvent, AfterLinkSaveEvent, AfterDeleteEvent)

Still the solution seems quite sick to me, as I'd need to go for:

  1. client A --HTTP request--> Server (spring-data-rest controller)
  2. Server (AfterXXXEvent in the spring-data-rest controller) --websocket message--> Spring websocket controller
  3. Spring websocket controller --websocket message via topic--> all Clients interested in the topic
  4. Server (spring-data-rest controller) --HTTP response--> client A

Scenario 2: Websocket API independent from REST API

Rules:

  • client request is REST/HTTP API for non-modifying operations only
  • response is REST/HTTP API for non-modifying operations only
  • client sends websocket message for all the modifying operations
  • websocket message is sent to client for all the modifying operations only

Well, if no other ideas come up, I'd go for the later one, but still, it would be great if I could have somehow generated C(R)UD methods exposed via websockets as well, something like spring-data-websockets and handle only the routes in my implementation.

As I feel like I'd have to manually expose (via *WebSocketControllers) all the CUD methods for all my entities. And I might be too lazy for that.

Ideas?

curls
  • 382
  • 1
  • 3
  • 16
Peter Butkovic
  • 11,143
  • 10
  • 57
  • 81
  • 1
    Interesting! Given that Spring 4.0 has a good support for websockets Spring Data REST should be able to message endpoints. Why not open a JIRA (https://jira.springsource.org/browse/DATAREST) against SDR? – Stackee007 Jan 22 '14 at 19:46
  • @saintbands thanks for the tip! I was considering that before as well. However the Stackoverflow way won. Still, I raised the issue: https://jira.springsource.org/browse/DATAREST-232 anyway that seems like the best way to get some ideas from spring-data-rest team itself. – Peter Butkovic Jan 22 '14 at 20:13
  • 1
    I'm going to put my vote in for this in the Spring issue as well. This is exactly what I'm looking to do. If I have to write corresponding controller methods for all of the SDR methods that really takes away some of the benefit. Did you end up going with one solution or the other? – bvulaj Nov 21 '14 at 06:00
  • @BrandonV nope. I didn't have time to go any further here. – Peter Butkovic Nov 21 '14 at 10:27
  • 1
    OMG This, I need this! – Nestor Ledon Apr 03 '15 at 14:55

2 Answers2

1

Scenario 2 talks about, in the last step, a single client.But I thought your requirement was for a topic since you wanted multiple clients. If I wanted to complete 2 for your stated requirement, then you might want to maintain a list of clients and implement your own queue or use a ForkJoinPool to message all your clients listening in on your WebSockets. Having said that, A topic is definitely more elegant here but overall looks too complicated with different interfaces

For all messages from client to server, just go with a simple wire protocol and use a collection to parameterize, it could be RParam1.......

At the server, you need a controller to map these to different requests(and operations). Somehow does not look like too much work. Hope this helps.

Wile E K
  • 11
  • 1
0

The same architecture has bugged my mind for a while now and it will be a long story if I want to mention all the drawbacks and advantages of it so let me jump into the implementation.

The second scenario is valid, but as you mentioned its better to perform the crud actions on same websocket session. This shall remove the need for HTTP handshakes on every request, and reduces the body size of messages, therefore you will have better latency. Meanwhile, you already have a persisting connection to a server, so why not make good use out of it?

I searched around for a while and after 6 years from your question, I still couldn't find any websocket protocols that can make this happen, so I decided to work on that by myself cause I needed it for another dummy project.

Another advantage of such protocol could be that it doesn't require much changes to your already written controllers. So it should be able to support Spring Framework (for example) annotations and make websocket endpoints out of it. The hard part about implementing such protocol in another framework like spring is that as its not nice to create ServletRequest and ServletResponse and convert them to your own websocket protocol, you loose some advantages. For example, any http filter you have written in your application till that moment, will be meaningless because its not really easy to pass your websocket messages through those filters.

About the protocol itself: I decided everything to be passed through json format, alongside a unique id for each request so we can map callbacks on client side to the request id. And of course there is a filter chain to add your filters to it.

Another hard to deal thing here is Spring Security as that too works like http filters in some cases. In my own lib I could finally handle annotations like @PreAuthorize but if you are using antMatchers in your HTTP Security Config, it would be a problem.

Therefore, creating websocket adapter to call http controllers will have many drawbacks.

You can check out the project here: Rest Over Websocket. Its written for Spring Boot.

Sepehr GH
  • 1,297
  • 1
  • 17
  • 39