Package 

Class BaseController


  • @Controller()@ConditionalOnBean(value = {IServer.class}) 
    public final class BaseController
    
                        

    This controller contains the websocket routes/event handlers.

    An IServer bean is required for this controller to be discovered. This requirement is enforced via a ConditionalOnBean annotation for the sake of failing gracefully, but this starter provides little to no benefit without this controller.

    • Method Summary

      Modifier and Type Method Description
      final Unit onConnect(SessionConnectEvent e) We listen for "onConnect" events to update the "connected" setting on the user, which (if implemented) updates indicators in the client, and, if this user is the admin of a game, lets the client know if/when users can claim the admin spot
      final Unit onDisconnect(SessionDisconnectEvent e) We listen for "onDisconnect" events to update the "connected" setting on the user, which (if implemented) updates indicators in the client, and, if this user is the admin of a game, lets the client know if/when users can claim the admin spot
      final String on400Error(IllegalArgumentException e) There are various require calls in the application.
      final String on500Error(IllegalStateException e) There are various check calls in the application.
      final String findLastGame(@ModelAttribute() User user) This is not a true subscription route.
      final Iterable<String> getGames() Use this route to get updates whenever there is a change to the list of games that a user can join.
      final IGame<IPlayer> getGame(@DestinationVariable() String gameCode) Use this route to get updates whenever there is a change to the game with code gameCodeWhen someone subscribes to game updates, we want to send them the current game so the UI can make an initial update.
      final String createGame(@DestinationVariable() String gameCode, @ModelAttribute() User user) Make a request to this route when you want to create a new game.
      final IGame<IPlayer> joinGame(@DestinationVariable() String gameCode, @Payload() Map<String, Object> settings, @ModelAttribute() User user) Make a request to this route when you want to join an existing game.
      final IGame<IPlayer> updateSettings(@DestinationVariable() String gameCode, @Payload() Map<String, Object> settings, @ModelAttribute() User user) Use this route when a user wants to update their settings (name, photo, etc).
      final String becomeAdmin(@DestinationVariable() String gameCode, @ModelAttribute() User user) Use this route when a user wants to try and claim the admin spot.
      • Methods inherited from class java.lang.Object

        clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    • Method Detail

      • onConnect

        @EventListener() final Unit onConnect(SessionConnectEvent e)

        We listen for "onConnect" events to update the "connected" setting on the user, which (if implemented) updates indicators in the client, and, if this user is the admin of a game, lets the client know if/when users can claim the admin spot

      • onDisconnect

        @EventListener() final Unit onDisconnect(SessionDisconnectEvent e)

        We listen for "onDisconnect" events to update the "connected" setting on the user, which (if implemented) updates indicators in the client, and, if this user is the admin of a game, lets the client know if/when users can claim the admin spot

      • on400Error

        @MessageExceptionHandler()@SendToUser(value = {/topic/errors/client}) final String on400Error(IllegalArgumentException e)

        There are various require calls in the application. They should pass, as the server isn't designed to be connected to directly via a custom HTTP request, but (a) anything can happen and (b) sometimes consuming applications prefer leaning on require to simplify the UI, so instead of failing, we want to catch every IllegalArgumentException and send back the message to the user. These errors can be ignored or subscribed to in the frontend.

      • on500Error

        @MessageExceptionHandler()@SendToUser(value = {/topic/errors/server}) final String on500Error(IllegalStateException e)

        There are various check calls in the application. They should pass, but sometimes bugs happen and the server gets into a bad state. Instead of failing, we want to catch every IllegalStateException and send back the message to the user. These errors can be ignored or subscribed to in the frontend.

      • findLastGame

        @SubscribeMapping(value = {/rejoin-game}) final String findLastGame(@ModelAttribute() User user)

        This is not a true subscription route. It behaves similar to a REST endpoint. There is no equivalent in web sockets, but it is relatively easy to implement using the stomp JS library.

        This "route" is used on page load as follows:

        • The user is in the middle of a game and is disconnected for some reason

        • The user reconnects and the page loads, and this route is subscribed to

        • The page will get a near instant response with the code of the game the user was dropped from

        • The application can automatically re-subscribe to the game, putting them right back into the action.

      • getGames

        @SubscribeMapping(value = {/games}) final Iterable<String> getGames()

        Use this route to get updates whenever there is a change to the list of games that a user can join.

        When someone subscribes to the game list, we want to send them the current list of open games so the UI can make an initial update.

      • getGame

        @SubscribeMapping(value = {/games/{gameCode}}) final IGame<IPlayer> getGame(@DestinationVariable() String gameCode)

        Use this route to get updates whenever there is a change to the game with code gameCode

        When someone subscribes to game updates, we want to send them the current game so the UI can make an initial update.

      • createGame

        @MessageMapping(value = {/games/{gameCode}/create})@SendToUser(value = {/topic/successes}) final String createGame(@DestinationVariable() String gameCode, @ModelAttribute() User user)

        Make a request to this route when you want to create a new game. Anyone can call this route, so it is up to the UI to restrict this route to the appropriate people.

        A success message will be sent to the client if this completes successfully.

      • joinGame

        @MessageMapping(value = {/games/{gameCode}/join})@SendTo(value = {/topic/games/{gameCode}}) final IGame<IPlayer> joinGame(@DestinationVariable() String gameCode, @Payload() Map<String, Object> settings, @ModelAttribute() User user)

        Make a request to this route when you want to join an existing game.

        An update will be sent to anyone that already joined the game.

      • updateSettings

        @MessageMapping(value = {/games/{gameCode}/update})@SendTo(value = {/topic/games/{gameCode}}) final IGame<IPlayer> updateSettings(@DestinationVariable() String gameCode, @Payload() Map<String, Object> settings, @ModelAttribute() User user)

        Use this route when a user wants to update their settings (name, photo, etc). It updates the settings and sends the updated game to the rest of the users.

      • becomeAdmin

        @MessageMapping(value = {/games/{gameCode}/become-admin})@SendToUser(value = {/topic/successes}) final String becomeAdmin(@DestinationVariable() String gameCode, @ModelAttribute() User user)

        Use this route when a user wants to try and claim the admin spot. It is only valid to call when the admin has been offline for a sufficient amount of time. Due to race conditions, the claim may fail, but it will do so gracefully.

        A success message will be sent to the user if the claim is successful.