For the latest stable version, please use Spring Framework 6.2.0!

WebSocket Scope

Each WebSocket session has a map of attributes. The map is attached as a header to inbound client messages and may be accessed from a controller method, as the following example shows:

@Controller
public class MyController {

	@MessageMapping("/action")
	public void handle(SimpMessageHeaderAccessor headerAccessor) {
		Map<String, Object> attrs = headerAccessor.getSessionAttributes();
		// ...
	}
}

You can declare a Spring-managed bean in the websocket scope. You can inject WebSocket-scoped beans into controllers and any channel interceptors registered on the clientInboundChannel. Those are typically singletons and live longer than any individual WebSocket session. Therefore, you need to use a scope proxy mode for WebSocket-scoped beans, as the following example shows:

@Component
@Scope(scopeName = "websocket", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class MyBean {

	@PostConstruct
	public void init() {
		// Invoked after dependencies injected
	}

	// ...

	@PreDestroy
	public void destroy() {
		// Invoked when the WebSocket session ends
	}
}

@Controller
public class MyController {

	private final MyBean myBean;

	@Autowired
	public MyController(MyBean myBean) {
		this.myBean = myBean;
	}

	@MessageMapping("/action")
	public void handle() {
		// this.myBean from the current WebSocket session
	}
}

As with any custom scope, Spring initializes a new MyBean instance the first time it is accessed from the controller and stores the instance in the WebSocket session attributes. The same instance is subsequently returned until the session ends. WebSocket-scoped beans have all Spring lifecycle methods invoked, as shown in the preceding examples.