3

Problem: @Autowired beans in @ServerEndpoint class are null

How can I make sure that this WebSocketController class below will be injected with beans, that is how can I make it managed by Spring? I can connect to the websocket so it works but gameService is always null inside the WebSocketController class instance, so I think that it is created by tomcat somehow and not Spring.

I'm using Spring boot. I just need to figure out how to inject beans into this websocket controller class.

WebSocketController class

@Component @ServerEndpoint("/sock") public class WebSocketController { @Autowired private GameService gameService; private static Set<Session> clients = Collections.synchronizedSet(new HashSet<Session>()); @OnMessage public void handleMessage(Session session, String message) throws IOException { session.getBasicRemote().sendText( "Reversed: " + new StringBuilder(message).reverse()); } @OnOpen public void onOpen(Session session) { clients.add(session); System.out.println("New client @"+session.getId()); if (gameService == null) System.out.println("game service null"); } @OnClose public void onClose(Session session) { clients.remove(session); System.out.println("Client disconnected @" + session.getId()); } } 

GameService interface and implementation

public interface GameService { List<Character> getCharacters(); } @Service public class GameServiceMockImpl implements GameService { @Override public List<Character> getCharacters() { List<Character> list = new ArrayList<>(); list.add(new Character("aaa","1.png",100)); list.add(new Character("aaa","2.jpg",100)); list.add(new Character("aaa","3.jpg",100)); return list; } } 

Application class

@SpringBootApplication public class App { public static void main(String args[]){ SpringApplication.run(App.class,args); } @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } } 

EDIT:

Using Spring 4 WebSockets doesn't work at all, I can't even connect via a browser.

@Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(myHandler(), "/myHandler"); } @Bean public WebSocketHandler myHandler() { return new MyHandler(); } } public class MyHandler extends TextWebSocketHandler { @Override public void handleTextMessage(WebSocketSession session, TextMessage message) { System.out.println(message.getPayload()); } } 

2 Answers 2

3

You are trying to integrate Spring and Java WebSocket API. A class annotated by @Component is registered to a spring bean and its instance is managed by spring but if a class is annotated by @ServerEndpoint it is registered to a server-side WebSocket endpoint and every time the corresponding endpoint's WebSocket is connected to the server, its instance is created and managed by JWA implementation. We you can't use both annotations together.

Either you can use CDI injection(your server should also support)

@ServerEndpoint("/sock") public class WebSocketController { @Inject private GameService gameService; 

Or have a look on this doc, Spring 4 has support for WebSocket

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for answering. I'd rather use Spring 4 WebSocket and I want to use the 'direct approach' without SockJS and stuff like that. So I created TextWebSocketHandler and WebSocketConfigurer. But it doesn't work. I cannot connect from a browser. It says in console that it mapped the given url to a text handler but still can't connect. I added code in the main post.
I had to allow connections from other origins and it works. So in the end I'm using Spring 4 websockets.
But just for tests. Eventually everything will be on the server
3

Maybe this article can help:

https://spring.io/blog/2013/05/23/spring-framework-4-0-m1-websocket-support

You can use dependency (with spring version > 4)

<dependency> <groupId>org.springframework</groupId> <artifactId>spring-websocket</artifactId> <version>${spring.version}</version> </dependency> 

And then simply

@ServerEndpoint(value = "/echo", configurator = SpringConfigurator.class) public class WebSocketEndpoint { @Inject private BroadcastService broadcaster; 

3 Comments

Nice and easy. That's the one that made it work for me!
Could you briefly explain this code.Please! i not figure out how to use this piece of code.
@Sushant You can read the article spring.io/blog/2013/05/23/… - all explanations there in the best form

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.